Require valid Mint for InitializeAccount

This commit is contained in:
Tyera Eulberg 2020-08-27 15:22:03 -06:00 committed by Michael Vines
parent 0b71752d45
commit b2b20444e5
3 changed files with 155 additions and 109 deletions

View File

@ -13,6 +13,9 @@ pub enum TokenError {
/// Insufficient funds for the operation requested. /// Insufficient funds for the operation requested.
#[error("Insufficient funds")] #[error("Insufficient funds")]
InsufficientFunds, InsufficientFunds,
/// Invalid Mint.
#[error("Invalid Mint")]
InvalidMint,
/// Account not associated with this Mint. /// Account not associated with this Mint.
#[error("Account not associated with this Mint")] #[error("Account not associated with this Mint")]
MintMismatch, MintMismatch,

View File

@ -37,8 +37,10 @@ pub enum TokenInstruction {
/// The freeze authority/multisignature of the mint. /// The freeze authority/multisignature of the mint.
freeze_authority: COption<Pubkey>, freeze_authority: COption<Pubkey>,
}, },
/// Initializes a new account to hold tokens. If this account is associated with the native mint /// Initializes a new account to hold tokens. If this account is associated with the native
/// then the token balance of the initialized account will be equal to the amount of SOL in the account. /// mint then the token balance of the initialized account will be equal to the amount of SOL
/// in the account. If this account is associated with another mint, that mint must be
/// initialized before this command can succeed.
/// ///
/// The `InitializeAccount` instruction requires no signers and MUST be included within /// The `InitializeAccount` instruction requires no signers and MUST be included within
/// the same Transaction as the system program's `CreateInstruction` that creates the account /// the same Transaction as the system program's `CreateInstruction` that creates the account

View File

@ -72,6 +72,12 @@ impl Processor {
return Err(TokenError::NotRentExempt.into()); return Err(TokenError::NotRentExempt.into());
} }
if *mint_info.key != crate::native_mint::id() {
let mut mint_info_data = mint_info.data.borrow_mut();
let _: &mut Mint = state::unpack(&mut mint_info_data)
.map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
}
account.mint = *mint_info.key; account.mint = *mint_info.key;
account.owner = *owner_info.key; account.owner = *owner_info.key;
account.delegate = COption::None; account.delegate = COption::None;
@ -674,6 +680,7 @@ impl PrintProgramError for TokenError {
info!("Error: Lamport balance below rent-exempt threshold") info!("Error: Lamport balance below rent-exempt threshold")
} }
TokenError::InsufficientFunds => info!("Error: insufficient funds"), TokenError::InsufficientFunds => info!("Error: insufficient funds"),
TokenError::InvalidMint => info!("Error: Invalid Mint"),
TokenError::MintMismatch => info!("Error: Account not associated with this Mint"), TokenError::MintMismatch => info!("Error: Account not associated with this Mint"),
TokenError::OwnerMismatch => info!("Error: owner does not match"), TokenError::OwnerMismatch => info!("Error: owner does not match"),
TokenError::FixedSupply => info!("Error: the total supply of this token is fixed"), TokenError::FixedSupply => info!("Error: the total supply of this token is fixed"),
@ -765,7 +772,7 @@ mod tests {
} }
#[test] #[test]
#[should_panic(expected = "Custom(2)")] #[should_panic(expected = "Custom(3)")]
fn test_error_unwrap() { fn test_error_unwrap() {
Err::<(), ProgramError>(return_token_error_as_program_error()).unwrap(); Err::<(), ProgramError>(return_token_error_as_program_error()).unwrap();
} }
@ -836,7 +843,8 @@ mod tests {
let owner_key = pubkey_rand(); let owner_key = pubkey_rand();
let mut owner_account = SolanaAccount::default(); let mut owner_account = SolanaAccount::default();
let mint_key = pubkey_rand(); let mint_key = pubkey_rand();
let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id); let mut mint_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// account is not rent exempt // account is not rent exempt
@ -855,6 +863,27 @@ mod tests {
account_account.lamports = account_minimum_balance(); account_account.lamports = account_minimum_balance();
// mint is not valid (not initialized)
assert_eq!(
Err(TokenError::InvalidMint.into()),
do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
vec![
&mut account_account,
&mut mint_account,
&mut owner_account,
&mut rent_sysvar
],
)
);
// create mint
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
@ -907,10 +936,15 @@ mod tests {
let mut mint_account = let mut mint_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mint2_key = pubkey_rand(); let mint2_key = pubkey_rand();
let mut mint2_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create mint
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
@ -949,22 +983,19 @@ mod tests {
// create mismatch account // create mismatch account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &mismatch_key, &mint2_key, &owner_key).unwrap(), initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
vec![ vec![
&mut mismatch_account, &mut mismatch_account,
&mut mint2_account, &mut mint_account,
&mut owner_account, &mut owner_account,
&mut rent_sysvar, &mut rent_sysvar,
], ],
) )
.unwrap(); .unwrap();
let account: &mut Account = state::unpack(&mut mismatch_account.data).unwrap();
account.mint = mint2_key;
// create new mint & mint to account // mint to account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account], vec![&mut mint_account, &mut account_account, &mut owner_account],
@ -1286,18 +1317,6 @@ mod tests {
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create account
do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
vec![
&mut account_account,
&mut owner_account,
&mut mint_account,
&mut rent_sysvar,
],
)
.unwrap();
// create mint-able token with zero supply // create mint-able token with zero supply
let decimals = 2; let decimals = 2;
do_process_instruction( do_process_instruction(
@ -1317,6 +1336,18 @@ mod tests {
} }
); );
// create account
do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
vec![
&mut account_account,
&mut mint_account,
&mut owner_account,
&mut rent_sysvar,
],
)
.unwrap();
// mint to // mint to
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
@ -1349,13 +1380,20 @@ mod tests {
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create mint
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
vec![ vec![
&mut account_account, &mut account_account,
&mut owner_account,
&mut mint_account, &mut mint_account,
&mut owner_account,
&mut rent_sysvar, &mut rent_sysvar,
], ],
) )
@ -1366,19 +1404,14 @@ mod tests {
initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
vec![ vec![
&mut account2_account, &mut account2_account,
&mut owner_account,
&mut mint_account, &mut mint_account,
&mut owner_account,
&mut rent_sysvar, &mut rent_sysvar,
], ],
) )
.unwrap(); .unwrap();
// create new mint & mint to account // mint to account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account], vec![&mut mint_account, &mut account_account, &mut owner_account],
@ -1478,6 +1511,20 @@ mod tests {
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create new mint with owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create mint with owner and freeze_authority
do_process_instruction(
initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
vec![&mut mint2_account, &mut rent_sysvar],
)
.unwrap();
// invalid account // invalid account
assert_eq!( assert_eq!(
Err(TokenError::UninitializedState.into()), Err(TokenError::UninitializedState.into()),
@ -1631,13 +1678,6 @@ mod tests {
) )
.unwrap(); .unwrap();
// create new mint with owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// wrong owner // wrong owner
assert_eq!( assert_eq!(
Err(TokenError::OwnerMismatch.into()), Err(TokenError::OwnerMismatch.into()),
@ -1735,13 +1775,6 @@ mod tests {
) )
); );
// create mint with owner and freeze_authority
do_process_instruction(
initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
vec![&mut mint2_account, &mut rent_sysvar],
)
.unwrap();
// set freeze_authority // set freeze_authority
do_process_instruction( do_process_instruction(
set_authority( set_authority(
@ -1812,13 +1845,18 @@ mod tests {
let mut mint_account = let mut mint_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mint2_key = pubkey_rand(); let mint2_key = pubkey_rand();
let mut mint2_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let uninitialized_key = pubkey_rand(); let uninitialized_key = pubkey_rand();
let mut uninitialized_account = let mut uninitialized_account =
SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id); SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create new mint with owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
@ -1857,22 +1895,17 @@ mod tests {
// create mismatch account // create mismatch account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &mismatch_key, &mint2_key, &owner_key).unwrap(), initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
vec![ vec![
&mut mismatch_account, &mut mismatch_account,
&mut mint2_account, &mut mint_account,
&mut owner_account, &mut owner_account,
&mut rent_sysvar, &mut rent_sysvar,
], ],
) )
.unwrap(); .unwrap();
let account: &mut Account = state::unpack(&mut mismatch_account.data).unwrap();
// create new mint with owner account.mint = mint2_key;
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// mint to // mint to
do_process_instruction( do_process_instruction(
@ -2001,10 +2034,15 @@ mod tests {
let mut mint_account = let mut mint_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mint2_key = pubkey_rand(); let mint2_key = pubkey_rand();
let mut mint2_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create new mint
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
@ -2043,22 +2081,19 @@ mod tests {
// create mismatch account // create mismatch account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &mismatch_key, &mint2_key, &owner_key).unwrap(), initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
vec![ vec![
&mut mismatch_account, &mut mismatch_account,
&mut mint2_account, &mut mint_account,
&mut owner_account, &mut owner_account,
&mut rent_sysvar, &mut rent_sysvar,
], ],
) )
.unwrap(); .unwrap();
let account: &mut Account = state::unpack(&mut mismatch_account.data).unwrap();
account.mint = mint2_key;
// create new mint // mint to account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account], vec![&mut mint_account, &mut account_account, &mut owner_account],
@ -2286,6 +2321,13 @@ mod tests {
) )
.unwrap(); .unwrap();
// create new mint with multisig owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account with multisig owner // create account with multisig owner
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
@ -2316,12 +2358,7 @@ mod tests {
) )
.unwrap(); .unwrap();
// create new mint with multisig owner // mint to account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
let account_info_iter = &mut signer_accounts.iter_mut(); let account_info_iter = &mut signer_accounts.iter_mut();
do_process_instruction( do_process_instruction(
mint_to( mint_to(
@ -2495,16 +2532,6 @@ mod tests {
let mint2_key = pubkey_rand(); let mint2_key = pubkey_rand();
let mut mint2_account = let mut mint2_account =
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
do_process_instruction(
initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
vec![
&mut account3_account,
&mut mint2_account,
&mut owner_account,
&mut rent_sysvar,
],
)
.unwrap();
do_process_instruction( do_process_instruction(
initialize_mint( initialize_mint(
&program_id, &program_id,
@ -2517,6 +2544,16 @@ mod tests {
vec![&mut mint2_account, &mut rent_sysvar], vec![&mut mint2_account, &mut rent_sysvar],
) )
.unwrap(); .unwrap();
do_process_instruction(
initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
vec![
&mut account3_account,
&mut mint2_account,
&mut owner_account,
&mut rent_sysvar,
],
)
.unwrap();
let account_info_iter = &mut signer_accounts.iter_mut(); let account_info_iter = &mut signer_accounts.iter_mut();
do_process_instruction( do_process_instruction(
mint_to( mint_to(
@ -2758,6 +2795,11 @@ mod tests {
); );
// initialize and mint to non-native account // initialize and mint to non-native account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
vec![ vec![
@ -2768,11 +2810,6 @@ mod tests {
], ],
) )
.unwrap(); .unwrap();
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
vec![ vec![
@ -3131,6 +3168,13 @@ mod tests {
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create new mint with owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create an account // create an account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
@ -3155,13 +3199,6 @@ mod tests {
) )
.unwrap(); .unwrap();
// create new mint with owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// mint the max to an account // mint the max to an account
do_process_instruction( do_process_instruction(
mint_to( mint_to(
@ -3297,6 +3334,13 @@ mod tests {
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create new mint and fund first account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
@ -3321,12 +3365,7 @@ mod tests {
) )
.unwrap(); .unwrap();
// create new mint and fund first account // fund first account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account], vec![&mut mint_account, &mut account_account, &mut owner_account],
@ -3471,6 +3510,13 @@ mod tests {
SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id); SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
let mut rent_sysvar = rent_sysvar(); let mut rent_sysvar = rent_sysvar();
// create new mint with owner different from account owner
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
// create account // create account
do_process_instruction( do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(), initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
@ -3483,12 +3529,7 @@ mod tests {
) )
.unwrap(); .unwrap();
// create new mint with owner different from account owner // mint to account
do_process_instruction(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar],
)
.unwrap();
do_process_instruction( do_process_instruction(
mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(), mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account], vec![&mut mint_account, &mut account_account, &mut owner_account],