1use {
4 crate::{
5 amount_to_ui_amount_string_trimmed,
6 error::TokenError,
7 instruction::{is_valid_signer_index, AuthorityType, TokenInstruction, MAX_SIGNERS},
8 state::{Account, AccountState, Mint, Multisig},
9 try_ui_amount_into_amount,
10 },
11 solana_program::{
12 account_info::{next_account_info, AccountInfo},
13 entrypoint::ProgramResult,
14 msg,
15 program::set_return_data,
16 program_error::ProgramError,
17 program_memory::sol_memcmp,
18 program_option::COption,
19 program_pack::{IsInitialized, Pack},
20 pubkey::{Pubkey, PUBKEY_BYTES},
21 system_program,
22 sysvar::{rent::Rent, Sysvar},
23 },
24};
25
26pub struct Processor {}
28impl Processor {
29 fn _process_initialize_mint(
30 accounts: &[AccountInfo],
31 decimals: u8,
32 mint_authority: Pubkey,
33 freeze_authority: COption<Pubkey>,
34 rent_sysvar_account: bool,
35 ) -> ProgramResult {
36 let account_info_iter = &mut accounts.iter();
37 let mint_info = next_account_info(account_info_iter)?;
38 let mint_data_len = mint_info.data_len();
39 let rent = if rent_sysvar_account {
40 Rent::from_account_info(next_account_info(account_info_iter)?)?
41 } else {
42 Rent::get()?
43 };
44
45 let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow())?;
46 if mint.is_initialized {
47 return Err(TokenError::AlreadyInUse.into());
48 }
49
50 if !rent.is_exempt(mint_info.lamports(), mint_data_len) {
51 return Err(TokenError::NotRentExempt.into());
52 }
53
54 mint.mint_authority = COption::Some(mint_authority);
55 mint.decimals = decimals;
56 mint.is_initialized = true;
57 mint.freeze_authority = freeze_authority;
58
59 Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
60
61 Ok(())
62 }
63
64 pub fn process_initialize_mint(
66 accounts: &[AccountInfo],
67 decimals: u8,
68 mint_authority: Pubkey,
69 freeze_authority: COption<Pubkey>,
70 ) -> ProgramResult {
71 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, true)
72 }
73
74 pub fn process_initialize_mint2(
77 accounts: &[AccountInfo],
78 decimals: u8,
79 mint_authority: Pubkey,
80 freeze_authority: COption<Pubkey>,
81 ) -> ProgramResult {
82 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, false)
83 }
84
85 fn _process_initialize_account(
86 program_id: &Pubkey,
87 accounts: &[AccountInfo],
88 owner: Option<&Pubkey>,
89 rent_sysvar_account: bool,
90 ) -> ProgramResult {
91 let account_info_iter = &mut accounts.iter();
92 let new_account_info = next_account_info(account_info_iter)?;
93 let mint_info = next_account_info(account_info_iter)?;
94 let owner = if let Some(owner) = owner {
95 owner
96 } else {
97 next_account_info(account_info_iter)?.key
98 };
99 let new_account_info_data_len = new_account_info.data_len();
100 let rent = if rent_sysvar_account {
101 Rent::from_account_info(next_account_info(account_info_iter)?)?
102 } else {
103 Rent::get()?
104 };
105
106 let mut account = Account::unpack_unchecked(&new_account_info.data.borrow())?;
107 if account.is_initialized() {
108 return Err(TokenError::AlreadyInUse.into());
109 }
110
111 if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) {
112 return Err(TokenError::NotRentExempt.into());
113 }
114
115 let is_native_mint = Self::cmp_pubkeys(mint_info.key, &crate::native_mint::id());
116 if !is_native_mint {
117 Self::check_account_owner(program_id, mint_info)?;
118 let _ = Mint::unpack(&mint_info.data.borrow_mut())
119 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
120 }
121
122 account.mint = *mint_info.key;
123 account.owner = *owner;
124 account.close_authority = COption::None;
125 account.delegate = COption::None;
126 account.delegated_amount = 0;
127 account.state = AccountState::Initialized;
128 if is_native_mint {
129 let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len);
130 account.is_native = COption::Some(rent_exempt_reserve);
131 account.amount = new_account_info
132 .lamports()
133 .checked_sub(rent_exempt_reserve)
134 .ok_or(TokenError::Overflow)?;
135 } else {
136 account.is_native = COption::None;
137 account.amount = 0;
138 };
139
140 Account::pack(account, &mut new_account_info.data.borrow_mut())?;
141
142 Ok(())
143 }
144
145 pub fn process_initialize_account(
148 program_id: &Pubkey,
149 accounts: &[AccountInfo],
150 ) -> ProgramResult {
151 Self::_process_initialize_account(program_id, accounts, None, true)
152 }
153
154 pub fn process_initialize_account2(
157 program_id: &Pubkey,
158 accounts: &[AccountInfo],
159 owner: Pubkey,
160 ) -> ProgramResult {
161 Self::_process_initialize_account(program_id, accounts, Some(&owner), true)
162 }
163
164 pub fn process_initialize_account3(
167 program_id: &Pubkey,
168 accounts: &[AccountInfo],
169 owner: Pubkey,
170 ) -> ProgramResult {
171 Self::_process_initialize_account(program_id, accounts, Some(&owner), false)
172 }
173
174 fn _process_initialize_multisig(
175 accounts: &[AccountInfo],
176 m: u8,
177 rent_sysvar_account: bool,
178 ) -> ProgramResult {
179 let account_info_iter = &mut accounts.iter();
180 let multisig_info = next_account_info(account_info_iter)?;
181 let multisig_info_data_len = multisig_info.data_len();
182 let rent = if rent_sysvar_account {
183 Rent::from_account_info(next_account_info(account_info_iter)?)?
184 } else {
185 Rent::get()?
186 };
187
188 let mut multisig = Multisig::unpack_unchecked(&multisig_info.data.borrow())?;
189 if multisig.is_initialized {
190 return Err(TokenError::AlreadyInUse.into());
191 }
192
193 if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) {
194 return Err(TokenError::NotRentExempt.into());
195 }
196
197 let signer_infos = account_info_iter.as_slice();
198 multisig.m = m;
199 multisig.n = signer_infos.len() as u8;
200 if !is_valid_signer_index(multisig.n as usize) {
201 return Err(TokenError::InvalidNumberOfProvidedSigners.into());
202 }
203 if !is_valid_signer_index(multisig.m as usize) {
204 return Err(TokenError::InvalidNumberOfRequiredSigners.into());
205 }
206 for (i, signer_info) in signer_infos.iter().enumerate() {
207 multisig.signers[i] = *signer_info.key;
208 }
209 multisig.is_initialized = true;
210
211 Multisig::pack(multisig, &mut multisig_info.data.borrow_mut())?;
212
213 Ok(())
214 }
215
216 pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
219 Self::_process_initialize_multisig(accounts, m, true)
220 }
221
222 pub fn process_initialize_multisig2(accounts: &[AccountInfo], m: u8) -> ProgramResult {
225 Self::_process_initialize_multisig(accounts, m, false)
226 }
227
228 pub fn process_transfer(
230 program_id: &Pubkey,
231 accounts: &[AccountInfo],
232 amount: u64,
233 expected_decimals: Option<u8>,
234 ) -> ProgramResult {
235 let account_info_iter = &mut accounts.iter();
236
237 let source_account_info = next_account_info(account_info_iter)?;
238
239 let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
240 Some((next_account_info(account_info_iter)?, expected_decimals))
241 } else {
242 None
243 };
244
245 let destination_account_info = next_account_info(account_info_iter)?;
246 let authority_info = next_account_info(account_info_iter)?;
247
248 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
249 let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
250
251 if source_account.is_frozen() || destination_account.is_frozen() {
252 return Err(TokenError::AccountFrozen.into());
253 }
254 if source_account.amount < amount {
255 return Err(TokenError::InsufficientFunds.into());
256 }
257 if !Self::cmp_pubkeys(&source_account.mint, &destination_account.mint) {
258 return Err(TokenError::MintMismatch.into());
259 }
260
261 if let Some((mint_info, expected_decimals)) = expected_mint_info {
262 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
263 return Err(TokenError::MintMismatch.into());
264 }
265
266 let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
267 if expected_decimals != mint.decimals {
268 return Err(TokenError::MintDecimalsMismatch.into());
269 }
270 }
271
272 let self_transfer =
273 Self::cmp_pubkeys(source_account_info.key, destination_account_info.key);
274
275 match source_account.delegate {
276 COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
277 Self::validate_owner(
278 program_id,
279 delegate,
280 authority_info,
281 account_info_iter.as_slice(),
282 )?;
283 if source_account.delegated_amount < amount {
284 return Err(TokenError::InsufficientFunds.into());
285 }
286 if !self_transfer {
287 source_account.delegated_amount = source_account
288 .delegated_amount
289 .checked_sub(amount)
290 .ok_or(TokenError::Overflow)?;
291 if source_account.delegated_amount == 0 {
292 source_account.delegate = COption::None;
293 }
294 }
295 }
296 _ => Self::validate_owner(
297 program_id,
298 &source_account.owner,
299 authority_info,
300 account_info_iter.as_slice(),
301 )?,
302 };
303
304 if self_transfer || amount == 0 {
305 Self::check_account_owner(program_id, source_account_info)?;
306 Self::check_account_owner(program_id, destination_account_info)?;
307 }
308
309 if self_transfer {
312 return Ok(());
313 }
314
315 source_account.amount = source_account
316 .amount
317 .checked_sub(amount)
318 .ok_or(TokenError::Overflow)?;
319 destination_account.amount = destination_account
320 .amount
321 .checked_add(amount)
322 .ok_or(TokenError::Overflow)?;
323
324 if source_account.is_native() {
325 let source_starting_lamports = source_account_info.lamports();
326 **source_account_info.lamports.borrow_mut() = source_starting_lamports
327 .checked_sub(amount)
328 .ok_or(TokenError::Overflow)?;
329
330 let destination_starting_lamports = destination_account_info.lamports();
331 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
332 .checked_add(amount)
333 .ok_or(TokenError::Overflow)?;
334 }
335
336 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
337 Account::pack(
338 destination_account,
339 &mut destination_account_info.data.borrow_mut(),
340 )?;
341
342 Ok(())
343 }
344
345 pub fn process_approve(
347 program_id: &Pubkey,
348 accounts: &[AccountInfo],
349 amount: u64,
350 expected_decimals: Option<u8>,
351 ) -> ProgramResult {
352 let account_info_iter = &mut accounts.iter();
353
354 let source_account_info = next_account_info(account_info_iter)?;
355
356 let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
357 Some((next_account_info(account_info_iter)?, expected_decimals))
358 } else {
359 None
360 };
361 let delegate_info = next_account_info(account_info_iter)?;
362 let owner_info = next_account_info(account_info_iter)?;
363
364 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
365
366 if source_account.is_frozen() {
367 return Err(TokenError::AccountFrozen.into());
368 }
369
370 if let Some((mint_info, expected_decimals)) = expected_mint_info {
371 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
372 return Err(TokenError::MintMismatch.into());
373 }
374
375 let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
376 if expected_decimals != mint.decimals {
377 return Err(TokenError::MintDecimalsMismatch.into());
378 }
379 }
380
381 Self::validate_owner(
382 program_id,
383 &source_account.owner,
384 owner_info,
385 account_info_iter.as_slice(),
386 )?;
387
388 source_account.delegate = COption::Some(*delegate_info.key);
389 source_account.delegated_amount = amount;
390
391 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
392
393 Ok(())
394 }
395
396 pub fn process_revoke(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
398 let account_info_iter = &mut accounts.iter();
399 let source_account_info = next_account_info(account_info_iter)?;
400
401 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
402
403 let owner_info = next_account_info(account_info_iter)?;
404
405 if source_account.is_frozen() {
406 return Err(TokenError::AccountFrozen.into());
407 }
408
409 Self::validate_owner(
410 program_id,
411 &source_account.owner,
412 owner_info,
413 account_info_iter.as_slice(),
414 )?;
415
416 source_account.delegate = COption::None;
417 source_account.delegated_amount = 0;
418
419 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
420
421 Ok(())
422 }
423
424 pub fn process_set_authority(
426 program_id: &Pubkey,
427 accounts: &[AccountInfo],
428 authority_type: AuthorityType,
429 new_authority: COption<Pubkey>,
430 ) -> ProgramResult {
431 let account_info_iter = &mut accounts.iter();
432 let account_info = next_account_info(account_info_iter)?;
433 let authority_info = next_account_info(account_info_iter)?;
434
435 if account_info.data_len() == Account::get_packed_len() {
436 let mut account = Account::unpack(&account_info.data.borrow())?;
437
438 if account.is_frozen() {
439 return Err(TokenError::AccountFrozen.into());
440 }
441
442 match authority_type {
443 AuthorityType::AccountOwner => {
444 Self::validate_owner(
445 program_id,
446 &account.owner,
447 authority_info,
448 account_info_iter.as_slice(),
449 )?;
450
451 if let COption::Some(authority) = new_authority {
452 account.owner = authority;
453 } else {
454 return Err(TokenError::InvalidInstruction.into());
455 }
456
457 account.delegate = COption::None;
458 account.delegated_amount = 0;
459
460 if account.is_native() {
461 account.close_authority = COption::None;
462 }
463 }
464 AuthorityType::CloseAccount => {
465 let authority = account.close_authority.unwrap_or(account.owner);
466 Self::validate_owner(
467 program_id,
468 &authority,
469 authority_info,
470 account_info_iter.as_slice(),
471 )?;
472 account.close_authority = new_authority;
473 }
474 _ => {
475 return Err(TokenError::AuthorityTypeNotSupported.into());
476 }
477 }
478 Account::pack(account, &mut account_info.data.borrow_mut())?;
479 } else if account_info.data_len() == Mint::get_packed_len() {
480 let mut mint = Mint::unpack(&account_info.data.borrow())?;
481 match authority_type {
482 AuthorityType::MintTokens => {
483 let mint_authority = mint
486 .mint_authority
487 .ok_or(Into::<ProgramError>::into(TokenError::FixedSupply))?;
488 Self::validate_owner(
489 program_id,
490 &mint_authority,
491 authority_info,
492 account_info_iter.as_slice(),
493 )?;
494 mint.mint_authority = new_authority;
495 }
496 AuthorityType::FreezeAccount => {
497 let freeze_authority = mint
500 .freeze_authority
501 .ok_or(Into::<ProgramError>::into(TokenError::MintCannotFreeze))?;
502 Self::validate_owner(
503 program_id,
504 &freeze_authority,
505 authority_info,
506 account_info_iter.as_slice(),
507 )?;
508 mint.freeze_authority = new_authority;
509 }
510 _ => {
511 return Err(TokenError::AuthorityTypeNotSupported.into());
512 }
513 }
514 Mint::pack(mint, &mut account_info.data.borrow_mut())?;
515 } else {
516 return Err(ProgramError::InvalidArgument);
517 }
518
519 Ok(())
520 }
521
522 pub fn process_mint_to(
524 program_id: &Pubkey,
525 accounts: &[AccountInfo],
526 amount: u64,
527 expected_decimals: Option<u8>,
528 ) -> ProgramResult {
529 let account_info_iter = &mut accounts.iter();
530 let mint_info = next_account_info(account_info_iter)?;
531 let destination_account_info = next_account_info(account_info_iter)?;
532 let owner_info = next_account_info(account_info_iter)?;
533
534 let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
535 if destination_account.is_frozen() {
536 return Err(TokenError::AccountFrozen.into());
537 }
538
539 if destination_account.is_native() {
540 return Err(TokenError::NativeNotSupported.into());
541 }
542 if !Self::cmp_pubkeys(mint_info.key, &destination_account.mint) {
543 return Err(TokenError::MintMismatch.into());
544 }
545
546 let mut mint = Mint::unpack(&mint_info.data.borrow())?;
547 if let Some(expected_decimals) = expected_decimals {
548 if expected_decimals != mint.decimals {
549 return Err(TokenError::MintDecimalsMismatch.into());
550 }
551 }
552
553 match mint.mint_authority {
554 COption::Some(mint_authority) => Self::validate_owner(
555 program_id,
556 &mint_authority,
557 owner_info,
558 account_info_iter.as_slice(),
559 )?,
560 COption::None => return Err(TokenError::FixedSupply.into()),
561 }
562
563 if amount == 0 {
564 Self::check_account_owner(program_id, mint_info)?;
565 Self::check_account_owner(program_id, destination_account_info)?;
566 }
567
568 destination_account.amount = destination_account
569 .amount
570 .checked_add(amount)
571 .ok_or(TokenError::Overflow)?;
572
573 mint.supply = mint
574 .supply
575 .checked_add(amount)
576 .ok_or(TokenError::Overflow)?;
577
578 Account::pack(
579 destination_account,
580 &mut destination_account_info.data.borrow_mut(),
581 )?;
582 Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
583
584 Ok(())
585 }
586
587 pub fn process_burn(
589 program_id: &Pubkey,
590 accounts: &[AccountInfo],
591 amount: u64,
592 expected_decimals: Option<u8>,
593 ) -> ProgramResult {
594 let account_info_iter = &mut accounts.iter();
595
596 let source_account_info = next_account_info(account_info_iter)?;
597 let mint_info = next_account_info(account_info_iter)?;
598 let authority_info = next_account_info(account_info_iter)?;
599
600 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
601 let mut mint = Mint::unpack(&mint_info.data.borrow())?;
602
603 if source_account.is_frozen() {
604 return Err(TokenError::AccountFrozen.into());
605 }
606 if source_account.is_native() {
607 return Err(TokenError::NativeNotSupported.into());
608 }
609 if source_account.amount < amount {
610 return Err(TokenError::InsufficientFunds.into());
611 }
612 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
613 return Err(TokenError::MintMismatch.into());
614 }
615
616 if let Some(expected_decimals) = expected_decimals {
617 if expected_decimals != mint.decimals {
618 return Err(TokenError::MintDecimalsMismatch.into());
619 }
620 }
621
622 if !source_account.is_owned_by_system_program_or_incinerator() {
623 match source_account.delegate {
624 COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
625 Self::validate_owner(
626 program_id,
627 delegate,
628 authority_info,
629 account_info_iter.as_slice(),
630 )?;
631
632 if source_account.delegated_amount < amount {
633 return Err(TokenError::InsufficientFunds.into());
634 }
635 source_account.delegated_amount = source_account
636 .delegated_amount
637 .checked_sub(amount)
638 .ok_or(TokenError::Overflow)?;
639 if source_account.delegated_amount == 0 {
640 source_account.delegate = COption::None;
641 }
642 }
643 _ => Self::validate_owner(
644 program_id,
645 &source_account.owner,
646 authority_info,
647 account_info_iter.as_slice(),
648 )?,
649 }
650 }
651
652 if amount == 0 {
653 Self::check_account_owner(program_id, source_account_info)?;
654 Self::check_account_owner(program_id, mint_info)?;
655 }
656
657 source_account.amount = source_account
658 .amount
659 .checked_sub(amount)
660 .ok_or(TokenError::Overflow)?;
661 mint.supply = mint
662 .supply
663 .checked_sub(amount)
664 .ok_or(TokenError::Overflow)?;
665
666 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
667 Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
668
669 Ok(())
670 }
671
672 pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
674 let account_info_iter = &mut accounts.iter();
675 let source_account_info = next_account_info(account_info_iter)?;
676 let destination_account_info = next_account_info(account_info_iter)?;
677 let authority_info = next_account_info(account_info_iter)?;
678
679 if Self::cmp_pubkeys(source_account_info.key, destination_account_info.key) {
680 return Err(ProgramError::InvalidAccountData);
681 }
682
683 let source_account = Account::unpack(&source_account_info.data.borrow())?;
684 if !source_account.is_native() && source_account.amount != 0 {
685 return Err(TokenError::NonNativeHasBalance.into());
686 }
687
688 let authority = source_account
689 .close_authority
690 .unwrap_or(source_account.owner);
691 if !source_account.is_owned_by_system_program_or_incinerator() {
692 Self::validate_owner(
693 program_id,
694 &authority,
695 authority_info,
696 account_info_iter.as_slice(),
697 )?;
698 } else if !solana_program::incinerator::check_id(destination_account_info.key) {
699 return Err(ProgramError::InvalidAccountData);
700 }
701
702 let destination_starting_lamports = destination_account_info.lamports();
703 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
704 .checked_add(source_account_info.lamports())
705 .ok_or(TokenError::Overflow)?;
706
707 **source_account_info.lamports.borrow_mut() = 0;
708 delete_account(source_account_info)?;
709
710 Ok(())
711 }
712
713 pub fn process_toggle_freeze_account(
716 program_id: &Pubkey,
717 accounts: &[AccountInfo],
718 freeze: bool,
719 ) -> ProgramResult {
720 let account_info_iter = &mut accounts.iter();
721 let source_account_info = next_account_info(account_info_iter)?;
722 let mint_info = next_account_info(account_info_iter)?;
723 let authority_info = next_account_info(account_info_iter)?;
724
725 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
726 if freeze && source_account.is_frozen() || !freeze && !source_account.is_frozen() {
727 return Err(TokenError::InvalidState.into());
728 }
729 if source_account.is_native() {
730 return Err(TokenError::NativeNotSupported.into());
731 }
732 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
733 return Err(TokenError::MintMismatch.into());
734 }
735
736 let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
737 match mint.freeze_authority {
738 COption::Some(authority) => Self::validate_owner(
739 program_id,
740 &authority,
741 authority_info,
742 account_info_iter.as_slice(),
743 ),
744 COption::None => Err(TokenError::MintCannotFreeze.into()),
745 }?;
746
747 source_account.state = if freeze {
748 AccountState::Frozen
749 } else {
750 AccountState::Initialized
751 };
752
753 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
754
755 Ok(())
756 }
757
758 pub fn process_sync_native(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
760 let account_info_iter = &mut accounts.iter();
761 let native_account_info = next_account_info(account_info_iter)?;
762 Self::check_account_owner(program_id, native_account_info)?;
763
764 let mut native_account = Account::unpack(&native_account_info.data.borrow())?;
765
766 if let COption::Some(rent_exempt_reserve) = native_account.is_native {
767 let new_amount = native_account_info
768 .lamports()
769 .checked_sub(rent_exempt_reserve)
770 .ok_or(TokenError::Overflow)?;
771 if new_amount < native_account.amount {
772 return Err(TokenError::InvalidState.into());
773 }
774 native_account.amount = new_amount;
775 } else {
776 return Err(TokenError::NonNativeNotSupported.into());
777 }
778
779 Account::pack(native_account, &mut native_account_info.data.borrow_mut())?;
780 Ok(())
781 }
782
783 pub fn process_get_account_data_size(
786 program_id: &Pubkey,
787 accounts: &[AccountInfo],
788 ) -> ProgramResult {
789 let account_info_iter = &mut accounts.iter();
790 let mint_info = next_account_info(account_info_iter)?;
792 Self::check_account_owner(program_id, mint_info)?;
793 let _ = Mint::unpack(&mint_info.data.borrow())
794 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
795 set_return_data(&Account::LEN.to_le_bytes());
796 Ok(())
797 }
798
799 pub fn process_initialize_immutable_owner(accounts: &[AccountInfo]) -> ProgramResult {
802 let account_info_iter = &mut accounts.iter();
803 let token_account_info = next_account_info(account_info_iter)?;
804 let account = Account::unpack_unchecked(&token_account_info.data.borrow())?;
805 if account.is_initialized() {
806 return Err(TokenError::AlreadyInUse.into());
807 }
808 msg!("Please upgrade to SPL Token 2022 for immutable owner support");
809 Ok(())
810 }
811
812 pub fn process_amount_to_ui_amount(
815 program_id: &Pubkey,
816 accounts: &[AccountInfo],
817 amount: u64,
818 ) -> ProgramResult {
819 let account_info_iter = &mut accounts.iter();
820 let mint_info = next_account_info(account_info_iter)?;
821 Self::check_account_owner(program_id, mint_info)?;
822
823 let mint = Mint::unpack(&mint_info.data.borrow_mut())
824 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
825 let ui_amount = amount_to_ui_amount_string_trimmed(amount, mint.decimals);
826
827 set_return_data(&ui_amount.into_bytes());
828 Ok(())
829 }
830
831 pub fn process_ui_amount_to_amount(
834 program_id: &Pubkey,
835 accounts: &[AccountInfo],
836 ui_amount: &str,
837 ) -> ProgramResult {
838 let account_info_iter = &mut accounts.iter();
839 let mint_info = next_account_info(account_info_iter)?;
840 Self::check_account_owner(program_id, mint_info)?;
841
842 let mint = Mint::unpack(&mint_info.data.borrow_mut())
843 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
844 let amount = try_ui_amount_into_amount(ui_amount.to_string(), mint.decimals)?;
845
846 set_return_data(&amount.to_le_bytes());
847 Ok(())
848 }
849
850 pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
852 let instruction = TokenInstruction::unpack(input)?;
853
854 match instruction {
855 TokenInstruction::InitializeMint {
856 decimals,
857 mint_authority,
858 freeze_authority,
859 } => {
860 msg!("Instruction: InitializeMint");
861 Self::process_initialize_mint(accounts, decimals, mint_authority, freeze_authority)
862 }
863 TokenInstruction::InitializeMint2 {
864 decimals,
865 mint_authority,
866 freeze_authority,
867 } => {
868 msg!("Instruction: InitializeMint2");
869 Self::process_initialize_mint2(accounts, decimals, mint_authority, freeze_authority)
870 }
871 TokenInstruction::InitializeAccount => {
872 msg!("Instruction: InitializeAccount");
873 Self::process_initialize_account(program_id, accounts)
874 }
875 TokenInstruction::InitializeAccount2 { owner } => {
876 msg!("Instruction: InitializeAccount2");
877 Self::process_initialize_account2(program_id, accounts, owner)
878 }
879 TokenInstruction::InitializeAccount3 { owner } => {
880 msg!("Instruction: InitializeAccount3");
881 Self::process_initialize_account3(program_id, accounts, owner)
882 }
883 TokenInstruction::InitializeMultisig { m } => {
884 msg!("Instruction: InitializeMultisig");
885 Self::process_initialize_multisig(accounts, m)
886 }
887 TokenInstruction::InitializeMultisig2 { m } => {
888 msg!("Instruction: InitializeMultisig2");
889 Self::process_initialize_multisig2(accounts, m)
890 }
891 TokenInstruction::Transfer { amount } => {
892 msg!("Instruction: Transfer");
893 Self::process_transfer(program_id, accounts, amount, None)
894 }
895 TokenInstruction::Approve { amount } => {
896 msg!("Instruction: Approve");
897 Self::process_approve(program_id, accounts, amount, None)
898 }
899 TokenInstruction::Revoke => {
900 msg!("Instruction: Revoke");
901 Self::process_revoke(program_id, accounts)
902 }
903 TokenInstruction::SetAuthority {
904 authority_type,
905 new_authority,
906 } => {
907 msg!("Instruction: SetAuthority");
908 Self::process_set_authority(program_id, accounts, authority_type, new_authority)
909 }
910 TokenInstruction::MintTo { amount } => {
911 msg!("Instruction: MintTo");
912 Self::process_mint_to(program_id, accounts, amount, None)
913 }
914 TokenInstruction::Burn { amount } => {
915 msg!("Instruction: Burn");
916 Self::process_burn(program_id, accounts, amount, None)
917 }
918 TokenInstruction::CloseAccount => {
919 msg!("Instruction: CloseAccount");
920 Self::process_close_account(program_id, accounts)
921 }
922 TokenInstruction::FreezeAccount => {
923 msg!("Instruction: FreezeAccount");
924 Self::process_toggle_freeze_account(program_id, accounts, true)
925 }
926 TokenInstruction::ThawAccount => {
927 msg!("Instruction: ThawAccount");
928 Self::process_toggle_freeze_account(program_id, accounts, false)
929 }
930 TokenInstruction::TransferChecked { amount, decimals } => {
931 msg!("Instruction: TransferChecked");
932 Self::process_transfer(program_id, accounts, amount, Some(decimals))
933 }
934 TokenInstruction::ApproveChecked { amount, decimals } => {
935 msg!("Instruction: ApproveChecked");
936 Self::process_approve(program_id, accounts, amount, Some(decimals))
937 }
938 TokenInstruction::MintToChecked { amount, decimals } => {
939 msg!("Instruction: MintToChecked");
940 Self::process_mint_to(program_id, accounts, amount, Some(decimals))
941 }
942 TokenInstruction::BurnChecked { amount, decimals } => {
943 msg!("Instruction: BurnChecked");
944 Self::process_burn(program_id, accounts, amount, Some(decimals))
945 }
946 TokenInstruction::SyncNative => {
947 msg!("Instruction: SyncNative");
948 Self::process_sync_native(program_id, accounts)
949 }
950 TokenInstruction::GetAccountDataSize => {
951 msg!("Instruction: GetAccountDataSize");
952 Self::process_get_account_data_size(program_id, accounts)
953 }
954 TokenInstruction::InitializeImmutableOwner => {
955 msg!("Instruction: InitializeImmutableOwner");
956 Self::process_initialize_immutable_owner(accounts)
957 }
958 TokenInstruction::AmountToUiAmount { amount } => {
959 msg!("Instruction: AmountToUiAmount");
960 Self::process_amount_to_ui_amount(program_id, accounts, amount)
961 }
962 TokenInstruction::UiAmountToAmount { ui_amount } => {
963 msg!("Instruction: UiAmountToAmount");
964 Self::process_ui_amount_to_amount(program_id, accounts, ui_amount)
965 }
966 }
967 }
968
969 pub fn check_account_owner(program_id: &Pubkey, account_info: &AccountInfo) -> ProgramResult {
971 if !Self::cmp_pubkeys(program_id, account_info.owner) {
972 Err(ProgramError::IncorrectProgramId)
973 } else {
974 Ok(())
975 }
976 }
977
978 pub fn cmp_pubkeys(a: &Pubkey, b: &Pubkey) -> bool {
981 sol_memcmp(a.as_ref(), b.as_ref(), PUBKEY_BYTES) == 0
982 }
983
984 pub fn validate_owner(
986 program_id: &Pubkey,
987 expected_owner: &Pubkey,
988 owner_account_info: &AccountInfo,
989 signers: &[AccountInfo],
990 ) -> ProgramResult {
991 if !Self::cmp_pubkeys(expected_owner, owner_account_info.key) {
992 return Err(TokenError::OwnerMismatch.into());
993 }
994 if Self::cmp_pubkeys(program_id, owner_account_info.owner)
995 && owner_account_info.data_len() == Multisig::get_packed_len()
996 {
997 let multisig = Multisig::unpack(&owner_account_info.data.borrow())?;
998 let mut num_signers = 0;
999 let mut matched = [false; MAX_SIGNERS];
1000 for signer in signers.iter() {
1001 for (position, key) in multisig.signers[0..multisig.n as usize].iter().enumerate() {
1002 if Self::cmp_pubkeys(key, signer.key) && !matched[position] {
1003 if !signer.is_signer {
1004 return Err(ProgramError::MissingRequiredSignature);
1005 }
1006 matched[position] = true;
1007 num_signers += 1;
1008 }
1009 }
1010 }
1011 if num_signers < multisig.m {
1012 return Err(ProgramError::MissingRequiredSignature);
1013 }
1014 return Ok(());
1015 } else if !owner_account_info.is_signer {
1016 return Err(ProgramError::MissingRequiredSignature);
1017 }
1018 Ok(())
1019 }
1020}
1021
1022#[cfg(not(target_os = "solana"))]
1026fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
1027 account_info.assign(&system_program::id());
1028 let mut account_data = account_info.data.borrow_mut();
1029 let data_len = account_data.len();
1030 solana_program::program_memory::sol_memset(*account_data, 0, data_len);
1031 Ok(())
1032}
1033
1034#[cfg(target_os = "solana")]
1036fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
1037 account_info.assign(&system_program::id());
1038 account_info.realloc(0, false)
1039}
1040
1041#[cfg(test)]
1042mod tests {
1043 use {
1044 super::*,
1045 crate::instruction::*,
1046 serial_test::serial,
1047 solana_program::{
1048 account_info::IntoAccountInfo,
1049 clock::Epoch,
1050 instruction::Instruction,
1051 program_error::{self, PrintProgramError},
1052 sysvar::rent,
1053 },
1054 solana_sdk::account::{
1055 create_account_for_test, create_is_signer_account_infos, Account as SolanaAccount,
1056 },
1057 std::sync::{Arc, RwLock},
1058 };
1059
1060 lazy_static::lazy_static! {
1061 static ref EXPECTED_DATA: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(Vec::new()));
1062 }
1063
1064 fn set_expected_data(expected_data: Vec<u8>) {
1065 *EXPECTED_DATA.write().unwrap() = expected_data;
1066 }
1067
1068 struct SyscallStubs {}
1069 impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
1070 fn sol_log(&self, _message: &str) {}
1071
1072 fn sol_invoke_signed(
1073 &self,
1074 _instruction: &Instruction,
1075 _account_infos: &[AccountInfo],
1076 _signers_seeds: &[&[&[u8]]],
1077 ) -> ProgramResult {
1078 Err(ProgramError::Custom(42)) }
1080
1081 fn sol_get_clock_sysvar(&self, _var_addr: *mut u8) -> u64 {
1082 program_error::UNSUPPORTED_SYSVAR
1083 }
1084
1085 fn sol_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
1086 program_error::UNSUPPORTED_SYSVAR
1087 }
1088
1089 #[allow(deprecated)]
1090 fn sol_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
1091 program_error::UNSUPPORTED_SYSVAR
1092 }
1093
1094 fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
1095 unsafe {
1096 *(var_addr as *mut _ as *mut Rent) = Rent::default();
1097 }
1098 solana_program::entrypoint::SUCCESS
1099 }
1100
1101 fn sol_set_return_data(&self, data: &[u8]) {
1102 assert_eq!(&*EXPECTED_DATA.write().unwrap(), data)
1103 }
1104 }
1105
1106 fn do_process_instruction(
1107 instruction: Instruction,
1108 accounts: Vec<&mut SolanaAccount>,
1109 ) -> ProgramResult {
1110 {
1111 use std::sync::Once;
1112 static ONCE: Once = Once::new();
1113
1114 ONCE.call_once(|| {
1115 solana_sdk::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
1116 });
1117 }
1118
1119 let mut meta = instruction
1120 .accounts
1121 .iter()
1122 .zip(accounts)
1123 .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
1124 .collect::<Vec<_>>();
1125
1126 let account_infos = create_is_signer_account_infos(&mut meta);
1127 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
1128 }
1129
1130 fn do_process_instruction_dups(
1131 instruction: Instruction,
1132 account_infos: Vec<AccountInfo>,
1133 ) -> ProgramResult {
1134 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
1135 }
1136
1137 fn return_token_error_as_program_error() -> ProgramError {
1138 TokenError::MintMismatch.into()
1139 }
1140
1141 fn rent_sysvar() -> SolanaAccount {
1142 create_account_for_test(&Rent::default())
1143 }
1144
1145 fn mint_minimum_balance() -> u64 {
1146 Rent::default().minimum_balance(Mint::get_packed_len())
1147 }
1148
1149 fn account_minimum_balance() -> u64 {
1150 Rent::default().minimum_balance(Account::get_packed_len())
1151 }
1152
1153 fn multisig_minimum_balance() -> u64 {
1154 Rent::default().minimum_balance(Multisig::get_packed_len())
1155 }
1156
1157 #[test]
1158 fn test_print_error() {
1159 let error = return_token_error_as_program_error();
1160 error.print::<TokenError>();
1161 }
1162
1163 #[test]
1164 fn test_error_as_custom() {
1165 assert_eq!(
1166 return_token_error_as_program_error(),
1167 ProgramError::Custom(3)
1168 );
1169 }
1170
1171 #[test]
1172 fn test_unique_account_sizes() {
1173 assert_ne!(Mint::get_packed_len(), 0);
1174 assert_ne!(Mint::get_packed_len(), Account::get_packed_len());
1175 assert_ne!(Mint::get_packed_len(), Multisig::get_packed_len());
1176 assert_ne!(Account::get_packed_len(), 0);
1177 assert_ne!(Account::get_packed_len(), Multisig::get_packed_len());
1178 assert_ne!(Multisig::get_packed_len(), 0);
1179 }
1180
1181 #[test]
1182 fn test_pack_unpack() {
1183 let check = Mint {
1185 mint_authority: COption::Some(Pubkey::new_from_array([1; 32])),
1186 supply: 42,
1187 decimals: 7,
1188 is_initialized: true,
1189 freeze_authority: COption::Some(Pubkey::new_from_array([2; 32])),
1190 };
1191 let mut packed = vec![0; Mint::get_packed_len() + 1];
1192 assert_eq!(
1193 Err(ProgramError::InvalidAccountData),
1194 Mint::pack(check, &mut packed)
1195 );
1196 let mut packed = vec![0; Mint::get_packed_len() - 1];
1197 assert_eq!(
1198 Err(ProgramError::InvalidAccountData),
1199 Mint::pack(check, &mut packed)
1200 );
1201 let mut packed = vec![0; Mint::get_packed_len()];
1202 Mint::pack(check, &mut packed).unwrap();
1203 let expect = vec![
1204 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1205 1, 1, 1, 1, 1, 1, 1, 42, 0, 0, 0, 0, 0, 0, 0, 7, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
1206 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1207 ];
1208 assert_eq!(packed, expect);
1209 let unpacked = Mint::unpack(&packed).unwrap();
1210 assert_eq!(unpacked, check);
1211
1212 let check = Account {
1214 mint: Pubkey::new_from_array([1; 32]),
1215 owner: Pubkey::new_from_array([2; 32]),
1216 amount: 3,
1217 delegate: COption::Some(Pubkey::new_from_array([4; 32])),
1218 state: AccountState::Frozen,
1219 is_native: COption::Some(5),
1220 delegated_amount: 6,
1221 close_authority: COption::Some(Pubkey::new_from_array([7; 32])),
1222 };
1223 let mut packed = vec![0; Account::get_packed_len() + 1];
1224 assert_eq!(
1225 Err(ProgramError::InvalidAccountData),
1226 Account::pack(check, &mut packed)
1227 );
1228 let mut packed = vec![0; Account::get_packed_len() - 1];
1229 assert_eq!(
1230 Err(ProgramError::InvalidAccountData),
1231 Account::pack(check, &mut packed)
1232 );
1233 let mut packed = vec![0; Account::get_packed_len()];
1234 Account::pack(check, &mut packed).unwrap();
1235 let expect = vec![
1236 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1237 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1238 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1239 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 0, 0, 5, 0, 0,
1240 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1241 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1242 ];
1243 assert_eq!(packed, expect);
1244 let unpacked = Account::unpack(&packed).unwrap();
1245 assert_eq!(unpacked, check);
1246
1247 let check = Multisig {
1249 m: 1,
1250 n: 2,
1251 is_initialized: true,
1252 signers: [Pubkey::new_from_array([3; 32]); MAX_SIGNERS],
1253 };
1254 let mut packed = vec![0; Multisig::get_packed_len() + 1];
1255 assert_eq!(
1256 Err(ProgramError::InvalidAccountData),
1257 Multisig::pack(check, &mut packed)
1258 );
1259 let mut packed = vec![0; Multisig::get_packed_len() - 1];
1260 assert_eq!(
1261 Err(ProgramError::InvalidAccountData),
1262 Multisig::pack(check, &mut packed)
1263 );
1264 let mut packed = vec![0; Multisig::get_packed_len()];
1265 Multisig::pack(check, &mut packed).unwrap();
1266 let expect = vec![
1267 1, 2, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1268 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1269 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1270 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1271 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1272 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1273 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1274 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1275 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1276 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1277 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1278 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1279 3, 3, 3, 3, 3, 3, 3,
1280 ];
1281 assert_eq!(packed, expect);
1282 let unpacked = Multisig::unpack(&packed).unwrap();
1283 assert_eq!(unpacked, check);
1284 }
1285
1286 #[test]
1287 fn test_initialize_mint() {
1288 let program_id = crate::id();
1289 let owner_key = Pubkey::new_unique();
1290 let mint_key = Pubkey::new_unique();
1291 let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
1292 let mint2_key = Pubkey::new_unique();
1293 let mut mint2_account =
1294 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1295 let mut rent_sysvar = rent_sysvar();
1296
1297 assert_eq!(
1299 Err(TokenError::NotRentExempt.into()),
1300 do_process_instruction(
1301 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1302 vec![&mut mint_account, &mut rent_sysvar]
1303 )
1304 );
1305
1306 mint_account.lamports = mint_minimum_balance();
1307
1308 do_process_instruction(
1310 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1311 vec![&mut mint_account, &mut rent_sysvar],
1312 )
1313 .unwrap();
1314
1315 assert_eq!(
1317 Err(TokenError::AlreadyInUse.into()),
1318 do_process_instruction(
1319 initialize_mint(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
1320 vec![&mut mint_account, &mut rent_sysvar]
1321 )
1322 );
1323
1324 do_process_instruction(
1326 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
1327 vec![&mut mint2_account, &mut rent_sysvar],
1328 )
1329 .unwrap();
1330 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
1331 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
1332 }
1333
1334 #[test]
1335 fn test_initialize_mint2() {
1336 let program_id = crate::id();
1337 let owner_key = Pubkey::new_unique();
1338 let mint_key = Pubkey::new_unique();
1339 let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
1340 let mint2_key = Pubkey::new_unique();
1341 let mut mint2_account =
1342 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1343
1344 assert_eq!(
1346 Err(TokenError::NotRentExempt.into()),
1347 do_process_instruction(
1348 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1349 vec![&mut mint_account]
1350 )
1351 );
1352
1353 mint_account.lamports = mint_minimum_balance();
1354
1355 do_process_instruction(
1357 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1358 vec![&mut mint_account],
1359 )
1360 .unwrap();
1361
1362 assert_eq!(
1364 Err(TokenError::AlreadyInUse.into()),
1365 do_process_instruction(
1366 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
1367 vec![&mut mint_account]
1368 )
1369 );
1370
1371 do_process_instruction(
1373 initialize_mint2(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
1374 vec![&mut mint2_account],
1375 )
1376 .unwrap();
1377 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
1378 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
1379 }
1380
1381 #[test]
1382 fn test_initialize_mint_account() {
1383 let program_id = crate::id();
1384 let account_key = Pubkey::new_unique();
1385 let mut account_account = SolanaAccount::new(42, Account::get_packed_len(), &program_id);
1386 let owner_key = Pubkey::new_unique();
1387 let mut owner_account = SolanaAccount::default();
1388 let mint_key = Pubkey::new_unique();
1389 let mut mint_account =
1390 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1391 let mut rent_sysvar = rent_sysvar();
1392
1393 assert_eq!(
1395 Err(TokenError::NotRentExempt.into()),
1396 do_process_instruction(
1397 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1398 vec![
1399 &mut account_account,
1400 &mut mint_account,
1401 &mut owner_account,
1402 &mut rent_sysvar
1403 ],
1404 )
1405 );
1406
1407 account_account.lamports = account_minimum_balance();
1408
1409 assert_eq!(
1411 Err(TokenError::InvalidMint.into()),
1412 do_process_instruction(
1413 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1414 vec![
1415 &mut account_account,
1416 &mut mint_account,
1417 &mut owner_account,
1418 &mut rent_sysvar
1419 ],
1420 )
1421 );
1422
1423 do_process_instruction(
1425 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1426 vec![&mut mint_account, &mut rent_sysvar],
1427 )
1428 .unwrap();
1429
1430 let not_program_id = Pubkey::new_unique();
1432 mint_account.owner = not_program_id;
1433 assert_eq!(
1434 Err(ProgramError::IncorrectProgramId),
1435 do_process_instruction(
1436 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1437 vec![
1438 &mut account_account,
1439 &mut mint_account,
1440 &mut owner_account,
1441 &mut rent_sysvar
1442 ],
1443 )
1444 );
1445 mint_account.owner = program_id;
1446
1447 do_process_instruction(
1449 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1450 vec![
1451 &mut account_account,
1452 &mut mint_account,
1453 &mut owner_account,
1454 &mut rent_sysvar,
1455 ],
1456 )
1457 .unwrap();
1458
1459 assert_eq!(
1461 Err(TokenError::AlreadyInUse.into()),
1462 do_process_instruction(
1463 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1464 vec![
1465 &mut account_account,
1466 &mut mint_account,
1467 &mut owner_account,
1468 &mut rent_sysvar
1469 ],
1470 )
1471 );
1472 }
1473
1474 #[test]
1475 fn test_transfer_dups() {
1476 let program_id = crate::id();
1477 let account1_key = Pubkey::new_unique();
1478 let mut account1_account = SolanaAccount::new(
1479 account_minimum_balance(),
1480 Account::get_packed_len(),
1481 &program_id,
1482 );
1483 let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
1484 let account2_key = Pubkey::new_unique();
1485 let mut account2_account = SolanaAccount::new(
1486 account_minimum_balance(),
1487 Account::get_packed_len(),
1488 &program_id,
1489 );
1490 let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
1491 let account3_key = Pubkey::new_unique();
1492 let mut account3_account = SolanaAccount::new(
1493 account_minimum_balance(),
1494 Account::get_packed_len(),
1495 &program_id,
1496 );
1497 let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
1498 let account4_key = Pubkey::new_unique();
1499 let mut account4_account = SolanaAccount::new(
1500 account_minimum_balance(),
1501 Account::get_packed_len(),
1502 &program_id,
1503 );
1504 let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
1505 let multisig_key = Pubkey::new_unique();
1506 let mut multisig_account = SolanaAccount::new(
1507 multisig_minimum_balance(),
1508 Multisig::get_packed_len(),
1509 &program_id,
1510 );
1511 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
1512 let owner_key = Pubkey::new_unique();
1513 let mut owner_account = SolanaAccount::default();
1514 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
1515 let mint_key = Pubkey::new_unique();
1516 let mut mint_account =
1517 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1518 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
1519 let rent_key = rent::id();
1520 let mut rent_sysvar = rent_sysvar();
1521 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
1522
1523 do_process_instruction_dups(
1525 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1526 vec![mint_info.clone(), rent_info.clone()],
1527 )
1528 .unwrap();
1529
1530 do_process_instruction_dups(
1532 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
1533 vec![
1534 account1_info.clone(),
1535 mint_info.clone(),
1536 account1_info.clone(),
1537 rent_info.clone(),
1538 ],
1539 )
1540 .unwrap();
1541
1542 do_process_instruction_dups(
1544 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
1545 vec![
1546 account2_info.clone(),
1547 mint_info.clone(),
1548 owner_info.clone(),
1549 rent_info.clone(),
1550 ],
1551 )
1552 .unwrap();
1553
1554 do_process_instruction_dups(
1556 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
1557 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
1558 )
1559 .unwrap();
1560
1561 do_process_instruction_dups(
1563 transfer(
1564 &program_id,
1565 &account1_key,
1566 &account2_key,
1567 &account1_key,
1568 &[],
1569 500,
1570 )
1571 .unwrap(),
1572 vec![
1573 account1_info.clone(),
1574 account2_info.clone(),
1575 account1_info.clone(),
1576 ],
1577 )
1578 .unwrap();
1579
1580 do_process_instruction_dups(
1582 transfer_checked(
1583 &program_id,
1584 &account1_key,
1585 &mint_key,
1586 &account2_key,
1587 &account1_key,
1588 &[],
1589 500,
1590 2,
1591 )
1592 .unwrap(),
1593 vec![
1594 account1_info.clone(),
1595 mint_info.clone(),
1596 account2_info.clone(),
1597 account1_info.clone(),
1598 ],
1599 )
1600 .unwrap();
1601
1602 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
1604 account.amount = 1000;
1605 account.delegated_amount = 1000;
1606 account.delegate = COption::Some(account1_key);
1607 account.owner = owner_key;
1608 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
1609
1610 do_process_instruction_dups(
1611 transfer(
1612 &program_id,
1613 &account1_key,
1614 &account2_key,
1615 &account1_key,
1616 &[],
1617 500,
1618 )
1619 .unwrap(),
1620 vec![
1621 account1_info.clone(),
1622 account2_info.clone(),
1623 account1_info.clone(),
1624 ],
1625 )
1626 .unwrap();
1627
1628 do_process_instruction_dups(
1630 transfer_checked(
1631 &program_id,
1632 &account1_key,
1633 &mint_key,
1634 &account2_key,
1635 &account1_key,
1636 &[],
1637 500,
1638 2,
1639 )
1640 .unwrap(),
1641 vec![
1642 account1_info.clone(),
1643 mint_info.clone(),
1644 account2_info.clone(),
1645 account1_info.clone(),
1646 ],
1647 )
1648 .unwrap();
1649
1650 do_process_instruction_dups(
1652 initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
1653 vec![
1654 account3_info.clone(),
1655 mint_info.clone(),
1656 account2_info.clone(),
1657 rent_info.clone(),
1658 ],
1659 )
1660 .unwrap();
1661 do_process_instruction_dups(
1662 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
1663 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
1664 )
1665 .unwrap();
1666
1667 account1_info.is_signer = false;
1668 account2_info.is_signer = true;
1669 do_process_instruction_dups(
1670 transfer(
1671 &program_id,
1672 &account3_key,
1673 &account2_key,
1674 &account2_key,
1675 &[],
1676 500,
1677 )
1678 .unwrap(),
1679 vec![
1680 account3_info.clone(),
1681 account2_info.clone(),
1682 account2_info.clone(),
1683 ],
1684 )
1685 .unwrap();
1686
1687 do_process_instruction_dups(
1689 transfer_checked(
1690 &program_id,
1691 &account3_key,
1692 &mint_key,
1693 &account2_key,
1694 &account2_key,
1695 &[],
1696 500,
1697 2,
1698 )
1699 .unwrap(),
1700 vec![
1701 account3_info.clone(),
1702 mint_info.clone(),
1703 account2_info.clone(),
1704 account2_info.clone(),
1705 ],
1706 )
1707 .unwrap();
1708
1709 do_process_instruction_dups(
1711 initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
1712 vec![
1713 multisig_info.clone(),
1714 rent_info.clone(),
1715 account4_info.clone(),
1716 ],
1717 )
1718 .unwrap();
1719
1720 do_process_instruction_dups(
1721 initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
1722 vec![
1723 account4_info.clone(),
1724 mint_info.clone(),
1725 multisig_info.clone(),
1726 rent_info.clone(),
1727 ],
1728 )
1729 .unwrap();
1730
1731 do_process_instruction_dups(
1732 mint_to(&program_id, &mint_key, &account4_key, &owner_key, &[], 1000).unwrap(),
1733 vec![mint_info.clone(), account4_info.clone(), owner_info.clone()],
1734 )
1735 .unwrap();
1736
1737 do_process_instruction_dups(
1739 transfer(
1740 &program_id,
1741 &account4_key,
1742 &account2_key,
1743 &multisig_key,
1744 &[&account4_key],
1745 500,
1746 )
1747 .unwrap(),
1748 vec![
1749 account4_info.clone(),
1750 account2_info.clone(),
1751 multisig_info.clone(),
1752 account4_info.clone(),
1753 ],
1754 )
1755 .unwrap();
1756
1757 do_process_instruction_dups(
1759 transfer_checked(
1760 &program_id,
1761 &account4_key,
1762 &mint_key,
1763 &account2_key,
1764 &multisig_key,
1765 &[&account4_key],
1766 500,
1767 2,
1768 )
1769 .unwrap(),
1770 vec![
1771 account4_info.clone(),
1772 mint_info.clone(),
1773 account2_info.clone(),
1774 multisig_info.clone(),
1775 account4_info.clone(),
1776 ],
1777 )
1778 .unwrap();
1779 }
1780
1781 #[test]
1782 fn test_transfer() {
1783 let program_id = crate::id();
1784 let account_key = Pubkey::new_unique();
1785 let mut account_account = SolanaAccount::new(
1786 account_minimum_balance(),
1787 Account::get_packed_len(),
1788 &program_id,
1789 );
1790 let account2_key = Pubkey::new_unique();
1791 let mut account2_account = SolanaAccount::new(
1792 account_minimum_balance(),
1793 Account::get_packed_len(),
1794 &program_id,
1795 );
1796 let account3_key = Pubkey::new_unique();
1797 let mut account3_account = SolanaAccount::new(
1798 account_minimum_balance(),
1799 Account::get_packed_len(),
1800 &program_id,
1801 );
1802 let delegate_key = Pubkey::new_unique();
1803 let mut delegate_account = SolanaAccount::default();
1804 let mismatch_key = Pubkey::new_unique();
1805 let mut mismatch_account = SolanaAccount::new(
1806 account_minimum_balance(),
1807 Account::get_packed_len(),
1808 &program_id,
1809 );
1810 let owner_key = Pubkey::new_unique();
1811 let mut owner_account = SolanaAccount::default();
1812 let owner2_key = Pubkey::new_unique();
1813 let mut owner2_account = SolanaAccount::default();
1814 let mint_key = Pubkey::new_unique();
1815 let mut mint_account =
1816 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1817 let mint2_key = Pubkey::new_unique();
1818 let mut rent_sysvar = rent_sysvar();
1819
1820 do_process_instruction(
1822 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1823 vec![&mut mint_account, &mut rent_sysvar],
1824 )
1825 .unwrap();
1826
1827 do_process_instruction(
1829 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1830 vec![
1831 &mut account_account,
1832 &mut mint_account,
1833 &mut owner_account,
1834 &mut rent_sysvar,
1835 ],
1836 )
1837 .unwrap();
1838
1839 do_process_instruction(
1841 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
1842 vec![
1843 &mut account2_account,
1844 &mut mint_account,
1845 &mut owner_account,
1846 &mut rent_sysvar,
1847 ],
1848 )
1849 .unwrap();
1850
1851 do_process_instruction(
1853 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
1854 vec![
1855 &mut account3_account,
1856 &mut mint_account,
1857 &mut owner_account,
1858 &mut rent_sysvar,
1859 ],
1860 )
1861 .unwrap();
1862
1863 do_process_instruction(
1865 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
1866 vec![
1867 &mut mismatch_account,
1868 &mut mint_account,
1869 &mut owner_account,
1870 &mut rent_sysvar,
1871 ],
1872 )
1873 .unwrap();
1874 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
1875 account.mint = mint2_key;
1876 Account::pack(account, &mut mismatch_account.data).unwrap();
1877
1878 do_process_instruction(
1880 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
1881 vec![&mut mint_account, &mut account_account, &mut owner_account],
1882 )
1883 .unwrap();
1884
1885 let mut instruction = transfer(
1887 &program_id,
1888 &account_key,
1889 &account2_key,
1890 &owner_key,
1891 &[],
1892 1000,
1893 )
1894 .unwrap();
1895 instruction.accounts[2].is_signer = false;
1896 assert_eq!(
1897 Err(ProgramError::MissingRequiredSignature),
1898 do_process_instruction(
1899 instruction,
1900 vec![
1901 &mut account_account,
1902 &mut account2_account,
1903 &mut owner_account,
1904 ],
1905 )
1906 );
1907
1908 assert_eq!(
1910 Err(TokenError::MintMismatch.into()),
1911 do_process_instruction(
1912 transfer(
1913 &program_id,
1914 &account_key,
1915 &mismatch_key,
1916 &owner_key,
1917 &[],
1918 1000
1919 )
1920 .unwrap(),
1921 vec![
1922 &mut account_account,
1923 &mut mismatch_account,
1924 &mut owner_account,
1925 ],
1926 )
1927 );
1928
1929 assert_eq!(
1931 Err(TokenError::OwnerMismatch.into()),
1932 do_process_instruction(
1933 transfer(
1934 &program_id,
1935 &account_key,
1936 &account2_key,
1937 &owner2_key,
1938 &[],
1939 1000
1940 )
1941 .unwrap(),
1942 vec![
1943 &mut account_account,
1944 &mut account2_account,
1945 &mut owner2_account,
1946 ],
1947 )
1948 );
1949
1950 let not_program_id = Pubkey::new_unique();
1952 account_account.owner = not_program_id;
1953 assert_eq!(
1954 Err(ProgramError::IncorrectProgramId),
1955 do_process_instruction(
1956 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
1957 vec![
1958 &mut account_account,
1959 &mut account2_account,
1960 &mut owner2_account,
1961 ],
1962 )
1963 );
1964 account_account.owner = program_id;
1965
1966 let not_program_id = Pubkey::new_unique();
1968 account2_account.owner = not_program_id;
1969 assert_eq!(
1970 Err(ProgramError::IncorrectProgramId),
1971 do_process_instruction(
1972 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
1973 vec![
1974 &mut account_account,
1975 &mut account2_account,
1976 &mut owner2_account,
1977 ],
1978 )
1979 );
1980 account2_account.owner = program_id;
1981
1982 do_process_instruction(
1984 transfer(
1985 &program_id,
1986 &account_key,
1987 &account2_key,
1988 &owner_key,
1989 &[],
1990 1000,
1991 )
1992 .unwrap(),
1993 vec![
1994 &mut account_account,
1995 &mut account2_account,
1996 &mut owner_account,
1997 ],
1998 )
1999 .unwrap();
2000
2001 assert_eq!(
2003 Err(TokenError::InsufficientFunds.into()),
2004 do_process_instruction(
2005 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
2006 vec![
2007 &mut account_account,
2008 &mut account2_account,
2009 &mut owner_account,
2010 ],
2011 )
2012 );
2013
2014 do_process_instruction(
2016 transfer(
2017 &program_id,
2018 &account2_key,
2019 &account_key,
2020 &owner_key,
2021 &[],
2022 500,
2023 )
2024 .unwrap(),
2025 vec![
2026 &mut account2_account,
2027 &mut account_account,
2028 &mut owner_account,
2029 ],
2030 )
2031 .unwrap();
2032
2033 assert_eq!(
2035 Err(TokenError::MintDecimalsMismatch.into()),
2036 do_process_instruction(
2037 transfer_checked(
2038 &program_id,
2039 &account2_key,
2040 &mint_key,
2041 &account_key,
2042 &owner_key,
2043 &[],
2044 1,
2045 10 )
2047 .unwrap(),
2048 vec![
2049 &mut account2_account,
2050 &mut mint_account,
2051 &mut account_account,
2052 &mut owner_account,
2053 ],
2054 )
2055 );
2056
2057 assert_eq!(
2059 Err(TokenError::MintMismatch.into()),
2060 do_process_instruction(
2061 transfer_checked(
2062 &program_id,
2063 &account2_key,
2064 &account3_key, &account_key,
2066 &owner_key,
2067 &[],
2068 1,
2069 2
2070 )
2071 .unwrap(),
2072 vec![
2073 &mut account2_account,
2074 &mut account3_account, &mut account_account,
2076 &mut owner_account,
2077 ],
2078 )
2079 );
2080 do_process_instruction(
2082 transfer_checked(
2083 &program_id,
2084 &account2_key,
2085 &mint_key,
2086 &account_key,
2087 &owner_key,
2088 &[],
2089 500,
2090 2,
2091 )
2092 .unwrap(),
2093 vec![
2094 &mut account2_account,
2095 &mut mint_account,
2096 &mut account_account,
2097 &mut owner_account,
2098 ],
2099 )
2100 .unwrap();
2101
2102 assert_eq!(
2104 Err(TokenError::InsufficientFunds.into()),
2105 do_process_instruction(
2106 transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
2107 vec![
2108 &mut account2_account,
2109 &mut account_account,
2110 &mut owner_account,
2111 ],
2112 )
2113 );
2114
2115 do_process_instruction(
2117 approve(
2118 &program_id,
2119 &account_key,
2120 &delegate_key,
2121 &owner_key,
2122 &[],
2123 100,
2124 )
2125 .unwrap(),
2126 vec![
2127 &mut account_account,
2128 &mut delegate_account,
2129 &mut owner_account,
2130 ],
2131 )
2132 .unwrap();
2133
2134 assert_eq!(
2136 Err(TokenError::OwnerMismatch.into()),
2137 do_process_instruction(
2138 transfer(
2139 &program_id,
2140 &account_key,
2141 &account2_key,
2142 &owner2_key, &[],
2144 1,
2145 )
2146 .unwrap(),
2147 vec![
2148 &mut account_account,
2149 &mut account2_account,
2150 &mut owner2_account,
2151 ],
2152 )
2153 );
2154
2155 assert_eq!(
2157 Err(TokenError::InsufficientFunds.into()),
2158 do_process_instruction(
2159 transfer(
2160 &program_id,
2161 &account_key,
2162 &account2_key,
2163 &delegate_key,
2164 &[],
2165 101
2166 )
2167 .unwrap(),
2168 vec![
2169 &mut account_account,
2170 &mut account2_account,
2171 &mut delegate_account,
2172 ],
2173 )
2174 );
2175
2176 do_process_instruction(
2178 transfer(
2179 &program_id,
2180 &account_key,
2181 &account2_key,
2182 &delegate_key,
2183 &[],
2184 100,
2185 )
2186 .unwrap(),
2187 vec![
2188 &mut account_account,
2189 &mut account2_account,
2190 &mut delegate_account,
2191 ],
2192 )
2193 .unwrap();
2194
2195 assert_eq!(
2197 Err(TokenError::OwnerMismatch.into()),
2198 do_process_instruction(
2199 transfer(
2200 &program_id,
2201 &account_key,
2202 &account2_key,
2203 &delegate_key,
2204 &[],
2205 1
2206 )
2207 .unwrap(),
2208 vec![
2209 &mut account_account,
2210 &mut account2_account,
2211 &mut delegate_account,
2212 ],
2213 )
2214 );
2215
2216 do_process_instruction(
2218 transfer(
2219 &program_id,
2220 &account_key,
2221 &account2_key,
2222 &owner_key,
2223 &[],
2224 900,
2225 )
2226 .unwrap(),
2227 vec![
2228 &mut account_account,
2229 &mut account2_account,
2230 &mut owner_account,
2231 ],
2232 )
2233 .unwrap();
2234
2235 do_process_instruction(
2237 approve(
2238 &program_id,
2239 &account_key,
2240 &delegate_key,
2241 &owner_key,
2242 &[],
2243 100,
2244 )
2245 .unwrap(),
2246 vec![
2247 &mut account_account,
2248 &mut delegate_account,
2249 &mut owner_account,
2250 ],
2251 )
2252 .unwrap();
2253
2254 assert_eq!(
2256 Err(TokenError::InsufficientFunds.into()),
2257 do_process_instruction(
2258 transfer(
2259 &program_id,
2260 &account_key,
2261 &account2_key,
2262 &delegate_key,
2263 &[],
2264 100
2265 )
2266 .unwrap(),
2267 vec![
2268 &mut account_account,
2269 &mut account2_account,
2270 &mut delegate_account,
2271 ],
2272 )
2273 );
2274 }
2275
2276 #[test]
2277 fn test_self_transfer() {
2278 let program_id = crate::id();
2279 let account_key = Pubkey::new_unique();
2280 let mut account_account = SolanaAccount::new(
2281 account_minimum_balance(),
2282 Account::get_packed_len(),
2283 &program_id,
2284 );
2285 let account2_key = Pubkey::new_unique();
2286 let mut account2_account = SolanaAccount::new(
2287 account_minimum_balance(),
2288 Account::get_packed_len(),
2289 &program_id,
2290 );
2291 let account3_key = Pubkey::new_unique();
2292 let mut account3_account = SolanaAccount::new(
2293 account_minimum_balance(),
2294 Account::get_packed_len(),
2295 &program_id,
2296 );
2297 let delegate_key = Pubkey::new_unique();
2298 let mut delegate_account = SolanaAccount::default();
2299 let owner_key = Pubkey::new_unique();
2300 let mut owner_account = SolanaAccount::default();
2301 let owner2_key = Pubkey::new_unique();
2302 let mut owner2_account = SolanaAccount::default();
2303 let mint_key = Pubkey::new_unique();
2304 let mut mint_account =
2305 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2306 let mut rent_sysvar = rent_sysvar();
2307
2308 do_process_instruction(
2310 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2311 vec![&mut mint_account, &mut rent_sysvar],
2312 )
2313 .unwrap();
2314
2315 do_process_instruction(
2317 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2318 vec![
2319 &mut account_account,
2320 &mut mint_account,
2321 &mut owner_account,
2322 &mut rent_sysvar,
2323 ],
2324 )
2325 .unwrap();
2326
2327 do_process_instruction(
2329 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2330 vec![
2331 &mut account2_account,
2332 &mut mint_account,
2333 &mut owner_account,
2334 &mut rent_sysvar,
2335 ],
2336 )
2337 .unwrap();
2338
2339 do_process_instruction(
2341 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
2342 vec![
2343 &mut account3_account,
2344 &mut mint_account,
2345 &mut owner_account,
2346 &mut rent_sysvar,
2347 ],
2348 )
2349 .unwrap();
2350
2351 do_process_instruction(
2353 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
2354 vec![&mut mint_account, &mut account_account, &mut owner_account],
2355 )
2356 .unwrap();
2357
2358 let account_info = (&account_key, false, &mut account_account).into_account_info();
2359 let account3_info = (&account3_key, false, &mut account3_account).into_account_info();
2360 let delegate_info = (&delegate_key, true, &mut delegate_account).into_account_info();
2361 let owner_info = (&owner_key, true, &mut owner_account).into_account_info();
2362 let owner2_info = (&owner2_key, true, &mut owner2_account).into_account_info();
2363 let mint_info = (&mint_key, false, &mut mint_account).into_account_info();
2364
2365 let instruction = transfer(
2367 &program_id,
2368 account_info.key,
2369 account_info.key,
2370 owner_info.key,
2371 &[],
2372 1000,
2373 )
2374 .unwrap();
2375 assert_eq!(
2376 Ok(()),
2377 Processor::process(
2378 &instruction.program_id,
2379 &[
2380 account_info.clone(),
2381 account_info.clone(),
2382 owner_info.clone(),
2383 ],
2384 &instruction.data,
2385 )
2386 );
2387 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2389 assert_eq!(account.amount, 1000);
2390
2391 let instruction = transfer_checked(
2393 &program_id,
2394 account_info.key,
2395 mint_info.key,
2396 account_info.key,
2397 owner_info.key,
2398 &[],
2399 1000,
2400 2,
2401 )
2402 .unwrap();
2403 assert_eq!(
2404 Ok(()),
2405 Processor::process(
2406 &instruction.program_id,
2407 &[
2408 account_info.clone(),
2409 mint_info.clone(),
2410 account_info.clone(),
2411 owner_info.clone(),
2412 ],
2413 &instruction.data,
2414 )
2415 );
2416 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2418 assert_eq!(account.amount, 1000);
2419
2420 let mut owner_no_sign_info = owner_info.clone();
2422 let mut instruction = transfer(
2423 &program_id,
2424 account_info.key,
2425 account_info.key,
2426 owner_no_sign_info.key,
2427 &[],
2428 1000,
2429 )
2430 .unwrap();
2431 instruction.accounts[2].is_signer = false;
2432 owner_no_sign_info.is_signer = false;
2433 assert_eq!(
2434 Err(ProgramError::MissingRequiredSignature),
2435 Processor::process(
2436 &instruction.program_id,
2437 &[
2438 account_info.clone(),
2439 account_info.clone(),
2440 owner_no_sign_info.clone(),
2441 ],
2442 &instruction.data,
2443 )
2444 );
2445
2446 let mut instruction = transfer_checked(
2448 &program_id,
2449 account_info.key,
2450 mint_info.key,
2451 account_info.key,
2452 owner_no_sign_info.key,
2453 &[],
2454 1000,
2455 2,
2456 )
2457 .unwrap();
2458 instruction.accounts[3].is_signer = false;
2459 assert_eq!(
2460 Err(ProgramError::MissingRequiredSignature),
2461 Processor::process(
2462 &instruction.program_id,
2463 &[
2464 account_info.clone(),
2465 mint_info.clone(),
2466 account_info.clone(),
2467 owner_no_sign_info,
2468 ],
2469 &instruction.data,
2470 )
2471 );
2472
2473 let instruction = transfer(
2475 &program_id,
2476 account_info.key,
2477 account_info.key,
2478 owner2_info.key,
2479 &[],
2480 1000,
2481 )
2482 .unwrap();
2483 assert_eq!(
2484 Err(TokenError::OwnerMismatch.into()),
2485 Processor::process(
2486 &instruction.program_id,
2487 &[
2488 account_info.clone(),
2489 account_info.clone(),
2490 owner2_info.clone(),
2491 ],
2492 &instruction.data,
2493 )
2494 );
2495
2496 let instruction = transfer_checked(
2498 &program_id,
2499 account_info.key,
2500 mint_info.key,
2501 account_info.key,
2502 owner2_info.key,
2503 &[],
2504 1000,
2505 2,
2506 )
2507 .unwrap();
2508 assert_eq!(
2509 Err(TokenError::OwnerMismatch.into()),
2510 Processor::process(
2511 &instruction.program_id,
2512 &[
2513 account_info.clone(),
2514 mint_info.clone(),
2515 account_info.clone(),
2516 owner2_info.clone(),
2517 ],
2518 &instruction.data,
2519 )
2520 );
2521
2522 let instruction = transfer(
2524 &program_id,
2525 account_info.key,
2526 account_info.key,
2527 owner_info.key,
2528 &[],
2529 1001,
2530 )
2531 .unwrap();
2532 assert_eq!(
2533 Err(TokenError::InsufficientFunds.into()),
2534 Processor::process(
2535 &instruction.program_id,
2536 &[
2537 account_info.clone(),
2538 account_info.clone(),
2539 owner_info.clone(),
2540 ],
2541 &instruction.data,
2542 )
2543 );
2544
2545 let instruction = transfer_checked(
2547 &program_id,
2548 account_info.key,
2549 mint_info.key,
2550 account_info.key,
2551 owner_info.key,
2552 &[],
2553 1001,
2554 2,
2555 )
2556 .unwrap();
2557 assert_eq!(
2558 Err(TokenError::InsufficientFunds.into()),
2559 Processor::process(
2560 &instruction.program_id,
2561 &[
2562 account_info.clone(),
2563 mint_info.clone(),
2564 account_info.clone(),
2565 owner_info.clone(),
2566 ],
2567 &instruction.data,
2568 )
2569 );
2570
2571 let instruction = transfer_checked(
2573 &program_id,
2574 account_info.key,
2575 mint_info.key,
2576 account_info.key,
2577 owner_info.key,
2578 &[],
2579 1,
2580 10, )
2582 .unwrap();
2583 assert_eq!(
2584 Err(TokenError::MintDecimalsMismatch.into()),
2585 Processor::process(
2586 &instruction.program_id,
2587 &[
2588 account_info.clone(),
2589 mint_info.clone(),
2590 account_info.clone(),
2591 owner_info.clone(),
2592 ],
2593 &instruction.data,
2594 )
2595 );
2596
2597 let instruction = transfer_checked(
2599 &program_id,
2600 account_info.key,
2601 account3_info.key, account_info.key,
2603 owner_info.key,
2604 &[],
2605 1,
2606 2,
2607 )
2608 .unwrap();
2609 assert_eq!(
2610 Err(TokenError::MintMismatch.into()),
2611 Processor::process(
2612 &instruction.program_id,
2613 &[
2614 account_info.clone(),
2615 account3_info.clone(), account_info.clone(),
2617 owner_info.clone(),
2618 ],
2619 &instruction.data,
2620 )
2621 );
2622
2623 let instruction = approve(
2625 &program_id,
2626 account_info.key,
2627 delegate_info.key,
2628 owner_info.key,
2629 &[],
2630 100,
2631 )
2632 .unwrap();
2633 Processor::process(
2634 &instruction.program_id,
2635 &[
2636 account_info.clone(),
2637 delegate_info.clone(),
2638 owner_info.clone(),
2639 ],
2640 &instruction.data,
2641 )
2642 .unwrap();
2643
2644 let instruction = transfer(
2646 &program_id,
2647 account_info.key,
2648 account_info.key,
2649 delegate_info.key,
2650 &[],
2651 100,
2652 )
2653 .unwrap();
2654 assert_eq!(
2655 Ok(()),
2656 Processor::process(
2657 &instruction.program_id,
2658 &[
2659 account_info.clone(),
2660 account_info.clone(),
2661 delegate_info.clone(),
2662 ],
2663 &instruction.data,
2664 )
2665 );
2666 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2668 assert_eq!(account.amount, 1000);
2669 assert_eq!(account.delegated_amount, 100);
2670
2671 let instruction = transfer_checked(
2673 &program_id,
2674 account_info.key,
2675 mint_info.key,
2676 account_info.key,
2677 delegate_info.key,
2678 &[],
2679 100,
2680 2,
2681 )
2682 .unwrap();
2683 assert_eq!(
2684 Ok(()),
2685 Processor::process(
2686 &instruction.program_id,
2687 &[
2688 account_info.clone(),
2689 mint_info.clone(),
2690 account_info.clone(),
2691 delegate_info.clone(),
2692 ],
2693 &instruction.data,
2694 )
2695 );
2696 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2698 assert_eq!(account.amount, 1000);
2699 assert_eq!(account.delegated_amount, 100);
2700
2701 let instruction = transfer(
2703 &program_id,
2704 account_info.key,
2705 account_info.key,
2706 delegate_info.key,
2707 &[],
2708 101,
2709 )
2710 .unwrap();
2711 assert_eq!(
2712 Err(TokenError::InsufficientFunds.into()),
2713 Processor::process(
2714 &instruction.program_id,
2715 &[
2716 account_info.clone(),
2717 account_info.clone(),
2718 delegate_info.clone(),
2719 ],
2720 &instruction.data,
2721 )
2722 );
2723
2724 let instruction = transfer_checked(
2726 &program_id,
2727 account_info.key,
2728 mint_info.key,
2729 account_info.key,
2730 delegate_info.key,
2731 &[],
2732 101,
2733 2,
2734 )
2735 .unwrap();
2736 assert_eq!(
2737 Err(TokenError::InsufficientFunds.into()),
2738 Processor::process(
2739 &instruction.program_id,
2740 &[
2741 account_info.clone(),
2742 mint_info.clone(),
2743 account_info.clone(),
2744 delegate_info.clone(),
2745 ],
2746 &instruction.data,
2747 )
2748 );
2749
2750 let instruction = transfer(
2752 &program_id,
2753 account_info.key,
2754 account_info.key,
2755 owner_info.key,
2756 &[],
2757 1000,
2758 )
2759 .unwrap();
2760 assert_eq!(
2761 Ok(()),
2762 Processor::process(
2763 &instruction.program_id,
2764 &[
2765 account_info.clone(),
2766 account_info.clone(),
2767 owner_info.clone(),
2768 ],
2769 &instruction.data,
2770 )
2771 );
2772 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2774 assert_eq!(account.amount, 1000);
2775
2776 let instruction = transfer_checked(
2778 &program_id,
2779 account_info.key,
2780 mint_info.key,
2781 account_info.key,
2782 owner_info.key,
2783 &[],
2784 1000,
2785 2,
2786 )
2787 .unwrap();
2788 assert_eq!(
2789 Ok(()),
2790 Processor::process(
2791 &instruction.program_id,
2792 &[
2793 account_info.clone(),
2794 mint_info.clone(),
2795 account_info.clone(),
2796 owner_info.clone(),
2797 ],
2798 &instruction.data,
2799 )
2800 );
2801 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2803 assert_eq!(account.amount, 1000);
2804 }
2805
2806 #[test]
2807 fn test_mintable_token_with_zero_supply() {
2808 let program_id = crate::id();
2809 let account_key = Pubkey::new_unique();
2810 let mut account_account = SolanaAccount::new(
2811 account_minimum_balance(),
2812 Account::get_packed_len(),
2813 &program_id,
2814 );
2815 let owner_key = Pubkey::new_unique();
2816 let mut owner_account = SolanaAccount::default();
2817 let mint_key = Pubkey::new_unique();
2818 let mut mint_account =
2819 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2820 let mut rent_sysvar = rent_sysvar();
2821
2822 let decimals = 2;
2824 do_process_instruction(
2825 initialize_mint(&program_id, &mint_key, &owner_key, None, decimals).unwrap(),
2826 vec![&mut mint_account, &mut rent_sysvar],
2827 )
2828 .unwrap();
2829 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
2830 assert_eq!(
2831 mint,
2832 Mint {
2833 mint_authority: COption::Some(owner_key),
2834 supply: 0,
2835 decimals,
2836 is_initialized: true,
2837 freeze_authority: COption::None,
2838 }
2839 );
2840
2841 do_process_instruction(
2843 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2844 vec![
2845 &mut account_account,
2846 &mut mint_account,
2847 &mut owner_account,
2848 &mut rent_sysvar,
2849 ],
2850 )
2851 .unwrap();
2852
2853 do_process_instruction(
2855 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
2856 vec![&mut mint_account, &mut account_account, &mut owner_account],
2857 )
2858 .unwrap();
2859 let _ = Mint::unpack(&mint_account.data).unwrap();
2860 let account = Account::unpack_unchecked(&account_account.data).unwrap();
2861 assert_eq!(account.amount, 42);
2862
2863 assert_eq!(
2865 Err(TokenError::MintDecimalsMismatch.into()),
2866 do_process_instruction(
2867 mint_to_checked(
2868 &program_id,
2869 &mint_key,
2870 &account_key,
2871 &owner_key,
2872 &[],
2873 42,
2874 decimals + 1
2875 )
2876 .unwrap(),
2877 vec![&mut mint_account, &mut account_account, &mut owner_account],
2878 )
2879 );
2880
2881 let _ = Mint::unpack(&mint_account.data).unwrap();
2882 let account = Account::unpack_unchecked(&account_account.data).unwrap();
2883 assert_eq!(account.amount, 42);
2884
2885 do_process_instruction(
2887 mint_to_checked(
2888 &program_id,
2889 &mint_key,
2890 &account_key,
2891 &owner_key,
2892 &[],
2893 42,
2894 decimals,
2895 )
2896 .unwrap(),
2897 vec![&mut mint_account, &mut account_account, &mut owner_account],
2898 )
2899 .unwrap();
2900 let _ = Mint::unpack(&mint_account.data).unwrap();
2901 let account = Account::unpack_unchecked(&account_account.data).unwrap();
2902 assert_eq!(account.amount, 84);
2903 }
2904
2905 #[test]
2906 fn test_approve_dups() {
2907 let program_id = crate::id();
2908 let account1_key = Pubkey::new_unique();
2909 let mut account1_account = SolanaAccount::new(
2910 account_minimum_balance(),
2911 Account::get_packed_len(),
2912 &program_id,
2913 );
2914 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
2915 let account2_key = Pubkey::new_unique();
2916 let mut account2_account = SolanaAccount::new(
2917 account_minimum_balance(),
2918 Account::get_packed_len(),
2919 &program_id,
2920 );
2921 let account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
2922 let account3_key = Pubkey::new_unique();
2923 let mut account3_account = SolanaAccount::new(
2924 account_minimum_balance(),
2925 Account::get_packed_len(),
2926 &program_id,
2927 );
2928 let account3_info: AccountInfo = (&account3_key, true, &mut account3_account).into();
2929 let multisig_key = Pubkey::new_unique();
2930 let mut multisig_account = SolanaAccount::new(
2931 multisig_minimum_balance(),
2932 Multisig::get_packed_len(),
2933 &program_id,
2934 );
2935 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
2936 let owner_key = Pubkey::new_unique();
2937 let mut owner_account = SolanaAccount::default();
2938 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
2939 let mint_key = Pubkey::new_unique();
2940 let mut mint_account =
2941 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2942 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
2943 let rent_key = rent::id();
2944 let mut rent_sysvar = rent_sysvar();
2945 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
2946
2947 do_process_instruction_dups(
2949 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2950 vec![mint_info.clone(), rent_info.clone()],
2951 )
2952 .unwrap();
2953
2954 do_process_instruction_dups(
2956 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
2957 vec![
2958 account1_info.clone(),
2959 mint_info.clone(),
2960 account1_info.clone(),
2961 rent_info.clone(),
2962 ],
2963 )
2964 .unwrap();
2965
2966 do_process_instruction_dups(
2968 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2969 vec![
2970 account2_info.clone(),
2971 mint_info.clone(),
2972 owner_info.clone(),
2973 rent_info.clone(),
2974 ],
2975 )
2976 .unwrap();
2977
2978 do_process_instruction_dups(
2980 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
2981 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
2982 )
2983 .unwrap();
2984
2985 do_process_instruction_dups(
2987 approve(
2988 &program_id,
2989 &account1_key,
2990 &account2_key,
2991 &account1_key,
2992 &[],
2993 500,
2994 )
2995 .unwrap(),
2996 vec![
2997 account1_info.clone(),
2998 account2_info.clone(),
2999 account1_info.clone(),
3000 ],
3001 )
3002 .unwrap();
3003
3004 do_process_instruction_dups(
3006 approve_checked(
3007 &program_id,
3008 &account1_key,
3009 &mint_key,
3010 &account2_key,
3011 &account1_key,
3012 &[],
3013 500,
3014 2,
3015 )
3016 .unwrap(),
3017 vec![
3018 account1_info.clone(),
3019 mint_info.clone(),
3020 account2_info.clone(),
3021 account1_info.clone(),
3022 ],
3023 )
3024 .unwrap();
3025
3026 do_process_instruction_dups(
3028 revoke(&program_id, &account1_key, &account1_key, &[]).unwrap(),
3029 vec![account1_info.clone(), account1_info.clone()],
3030 )
3031 .unwrap();
3032
3033 do_process_instruction_dups(
3035 initialize_multisig(&program_id, &multisig_key, &[&account3_key], 1).unwrap(),
3036 vec![
3037 multisig_info.clone(),
3038 rent_info.clone(),
3039 account3_info.clone(),
3040 ],
3041 )
3042 .unwrap();
3043
3044 do_process_instruction_dups(
3045 initialize_account(&program_id, &account3_key, &mint_key, &multisig_key).unwrap(),
3046 vec![
3047 account3_info.clone(),
3048 mint_info.clone(),
3049 multisig_info.clone(),
3050 rent_info.clone(),
3051 ],
3052 )
3053 .unwrap();
3054
3055 do_process_instruction_dups(
3056 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
3057 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
3058 )
3059 .unwrap();
3060
3061 do_process_instruction_dups(
3063 approve(
3064 &program_id,
3065 &account3_key,
3066 &account2_key,
3067 &multisig_key,
3068 &[&account3_key],
3069 500,
3070 )
3071 .unwrap(),
3072 vec![
3073 account3_info.clone(),
3074 account2_info.clone(),
3075 multisig_info.clone(),
3076 account3_info.clone(),
3077 ],
3078 )
3079 .unwrap();
3080
3081 do_process_instruction_dups(
3083 approve_checked(
3084 &program_id,
3085 &account3_key,
3086 &mint_key,
3087 &account2_key,
3088 &multisig_key,
3089 &[&account3_key],
3090 500,
3091 2,
3092 )
3093 .unwrap(),
3094 vec![
3095 account3_info.clone(),
3096 mint_info.clone(),
3097 account2_info.clone(),
3098 multisig_info.clone(),
3099 account3_info.clone(),
3100 ],
3101 )
3102 .unwrap();
3103
3104 do_process_instruction_dups(
3106 revoke(&program_id, &account3_key, &multisig_key, &[&account3_key]).unwrap(),
3107 vec![
3108 account3_info.clone(),
3109 multisig_info.clone(),
3110 account3_info.clone(),
3111 ],
3112 )
3113 .unwrap();
3114 }
3115
3116 #[test]
3117 fn test_approve() {
3118 let program_id = crate::id();
3119 let account_key = Pubkey::new_unique();
3120 let mut account_account = SolanaAccount::new(
3121 account_minimum_balance(),
3122 Account::get_packed_len(),
3123 &program_id,
3124 );
3125 let account2_key = Pubkey::new_unique();
3126 let mut account2_account = SolanaAccount::new(
3127 account_minimum_balance(),
3128 Account::get_packed_len(),
3129 &program_id,
3130 );
3131 let delegate_key = Pubkey::new_unique();
3132 let mut delegate_account = SolanaAccount::default();
3133 let owner_key = Pubkey::new_unique();
3134 let mut owner_account = SolanaAccount::default();
3135 let owner2_key = Pubkey::new_unique();
3136 let mut owner2_account = SolanaAccount::default();
3137 let mint_key = Pubkey::new_unique();
3138 let mut mint_account =
3139 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3140 let mut rent_sysvar = rent_sysvar();
3141
3142 do_process_instruction(
3144 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3145 vec![&mut mint_account, &mut rent_sysvar],
3146 )
3147 .unwrap();
3148
3149 do_process_instruction(
3151 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3152 vec![
3153 &mut account_account,
3154 &mut mint_account,
3155 &mut owner_account,
3156 &mut rent_sysvar,
3157 ],
3158 )
3159 .unwrap();
3160
3161 do_process_instruction(
3163 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3164 vec![
3165 &mut account2_account,
3166 &mut mint_account,
3167 &mut owner_account,
3168 &mut rent_sysvar,
3169 ],
3170 )
3171 .unwrap();
3172
3173 do_process_instruction(
3175 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
3176 vec![&mut mint_account, &mut account_account, &mut owner_account],
3177 )
3178 .unwrap();
3179
3180 let mut instruction = approve(
3182 &program_id,
3183 &account_key,
3184 &delegate_key,
3185 &owner_key,
3186 &[],
3187 100,
3188 )
3189 .unwrap();
3190 instruction.accounts[2].is_signer = false;
3191 assert_eq!(
3192 Err(ProgramError::MissingRequiredSignature),
3193 do_process_instruction(
3194 instruction,
3195 vec![
3196 &mut account_account,
3197 &mut delegate_account,
3198 &mut owner_account,
3199 ],
3200 )
3201 );
3202
3203 assert_eq!(
3205 Err(TokenError::OwnerMismatch.into()),
3206 do_process_instruction(
3207 approve(
3208 &program_id,
3209 &account_key,
3210 &delegate_key,
3211 &owner2_key,
3212 &[],
3213 100
3214 )
3215 .unwrap(),
3216 vec![
3217 &mut account_account,
3218 &mut delegate_account,
3219 &mut owner2_account,
3220 ],
3221 )
3222 );
3223
3224 do_process_instruction(
3226 approve(
3227 &program_id,
3228 &account_key,
3229 &delegate_key,
3230 &owner_key,
3231 &[],
3232 100,
3233 )
3234 .unwrap(),
3235 vec![
3236 &mut account_account,
3237 &mut delegate_account,
3238 &mut owner_account,
3239 ],
3240 )
3241 .unwrap();
3242
3243 assert_eq!(
3245 Err(TokenError::MintDecimalsMismatch.into()),
3246 do_process_instruction(
3247 approve_checked(
3248 &program_id,
3249 &account_key,
3250 &mint_key,
3251 &delegate_key,
3252 &owner_key,
3253 &[],
3254 100,
3255 0 )
3257 .unwrap(),
3258 vec![
3259 &mut account_account,
3260 &mut mint_account,
3261 &mut delegate_account,
3262 &mut owner_account,
3263 ],
3264 )
3265 );
3266
3267 assert_eq!(
3269 Err(TokenError::MintMismatch.into()),
3270 do_process_instruction(
3271 approve_checked(
3272 &program_id,
3273 &account_key,
3274 &account2_key, &delegate_key,
3276 &owner_key,
3277 &[],
3278 100,
3279 0
3280 )
3281 .unwrap(),
3282 vec![
3283 &mut account_account,
3284 &mut account2_account, &mut delegate_account,
3286 &mut owner_account,
3287 ],
3288 )
3289 );
3290
3291 do_process_instruction(
3293 approve_checked(
3294 &program_id,
3295 &account_key,
3296 &mint_key,
3297 &delegate_key,
3298 &owner_key,
3299 &[],
3300 100,
3301 2,
3302 )
3303 .unwrap(),
3304 vec![
3305 &mut account_account,
3306 &mut mint_account,
3307 &mut delegate_account,
3308 &mut owner_account,
3309 ],
3310 )
3311 .unwrap();
3312
3313 do_process_instruction(
3315 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
3316 vec![&mut account_account, &mut owner_account],
3317 )
3318 .unwrap();
3319 }
3320
3321 #[test]
3322 fn test_set_authority_dups() {
3323 let program_id = crate::id();
3324 let account1_key = Pubkey::new_unique();
3325 let mut account1_account = SolanaAccount::new(
3326 account_minimum_balance(),
3327 Account::get_packed_len(),
3328 &program_id,
3329 );
3330 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
3331 let owner_key = Pubkey::new_unique();
3332 let mint_key = Pubkey::new_unique();
3333 let mut mint_account =
3334 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3335 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
3336 let rent_key = rent::id();
3337 let mut rent_sysvar = rent_sysvar();
3338 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
3339
3340 do_process_instruction_dups(
3342 initialize_mint(&program_id, &mint_key, &mint_key, Some(&mint_key), 2).unwrap(),
3343 vec![mint_info.clone(), rent_info.clone()],
3344 )
3345 .unwrap();
3346
3347 do_process_instruction_dups(
3349 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
3350 vec![
3351 account1_info.clone(),
3352 mint_info.clone(),
3353 account1_info.clone(),
3354 rent_info.clone(),
3355 ],
3356 )
3357 .unwrap();
3358
3359 do_process_instruction_dups(
3361 set_authority(
3362 &program_id,
3363 &mint_key,
3364 Some(&owner_key),
3365 AuthorityType::MintTokens,
3366 &mint_key,
3367 &[],
3368 )
3369 .unwrap(),
3370 vec![mint_info.clone(), mint_info.clone()],
3371 )
3372 .unwrap();
3373
3374 do_process_instruction_dups(
3376 set_authority(
3377 &program_id,
3378 &mint_key,
3379 Some(&owner_key),
3380 AuthorityType::FreezeAccount,
3381 &mint_key,
3382 &[],
3383 )
3384 .unwrap(),
3385 vec![mint_info.clone(), mint_info.clone()],
3386 )
3387 .unwrap();
3388
3389 do_process_instruction_dups(
3391 set_authority(
3392 &program_id,
3393 &account1_key,
3394 Some(&owner_key),
3395 AuthorityType::AccountOwner,
3396 &account1_key,
3397 &[],
3398 )
3399 .unwrap(),
3400 vec![account1_info.clone(), account1_info.clone()],
3401 )
3402 .unwrap();
3403
3404 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
3406 account.close_authority = COption::Some(account1_key);
3407 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
3408
3409 do_process_instruction_dups(
3410 set_authority(
3411 &program_id,
3412 &account1_key,
3413 Some(&owner_key),
3414 AuthorityType::CloseAccount,
3415 &account1_key,
3416 &[],
3417 )
3418 .unwrap(),
3419 vec![account1_info.clone(), account1_info.clone()],
3420 )
3421 .unwrap();
3422 }
3423
3424 #[test]
3425 fn test_set_authority() {
3426 let program_id = crate::id();
3427 let account_key = Pubkey::new_unique();
3428 let mut account_account = SolanaAccount::new(
3429 account_minimum_balance(),
3430 Account::get_packed_len(),
3431 &program_id,
3432 );
3433 let account2_key = Pubkey::new_unique();
3434 let mut account2_account = SolanaAccount::new(
3435 account_minimum_balance(),
3436 Account::get_packed_len(),
3437 &program_id,
3438 );
3439 let owner_key = Pubkey::new_unique();
3440 let mut owner_account = SolanaAccount::default();
3441 let owner2_key = Pubkey::new_unique();
3442 let mut owner2_account = SolanaAccount::default();
3443 let owner3_key = Pubkey::new_unique();
3444 let mut owner3_account = SolanaAccount::default();
3445 let mint_key = Pubkey::new_unique();
3446 let mut mint_account =
3447 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3448 let mint2_key = Pubkey::new_unique();
3449 let mut mint2_account =
3450 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3451 let mut rent_sysvar = rent_sysvar();
3452
3453 do_process_instruction(
3455 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3456 vec![&mut mint_account, &mut rent_sysvar],
3457 )
3458 .unwrap();
3459
3460 do_process_instruction(
3462 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
3463 vec![&mut mint2_account, &mut rent_sysvar],
3464 )
3465 .unwrap();
3466
3467 assert_eq!(
3469 Err(ProgramError::UninitializedAccount),
3470 do_process_instruction(
3471 set_authority(
3472 &program_id,
3473 &account_key,
3474 Some(&owner2_key),
3475 AuthorityType::AccountOwner,
3476 &owner_key,
3477 &[]
3478 )
3479 .unwrap(),
3480 vec![&mut account_account, &mut owner_account],
3481 )
3482 );
3483
3484 do_process_instruction(
3486 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3487 vec![
3488 &mut account_account,
3489 &mut mint_account,
3490 &mut owner_account,
3491 &mut rent_sysvar,
3492 ],
3493 )
3494 .unwrap();
3495
3496 do_process_instruction(
3498 initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
3499 vec![
3500 &mut account2_account,
3501 &mut mint2_account,
3502 &mut owner_account,
3503 &mut rent_sysvar,
3504 ],
3505 )
3506 .unwrap();
3507
3508 assert_eq!(
3510 Err(TokenError::OwnerMismatch.into()),
3511 do_process_instruction(
3512 set_authority(
3513 &program_id,
3514 &account_key,
3515 Some(&owner_key),
3516 AuthorityType::AccountOwner,
3517 &owner2_key,
3518 &[]
3519 )
3520 .unwrap(),
3521 vec![&mut account_account, &mut owner2_account],
3522 )
3523 );
3524
3525 let mut instruction = set_authority(
3527 &program_id,
3528 &account_key,
3529 Some(&owner2_key),
3530 AuthorityType::AccountOwner,
3531 &owner_key,
3532 &[],
3533 )
3534 .unwrap();
3535 instruction.accounts[1].is_signer = false;
3536 assert_eq!(
3537 Err(ProgramError::MissingRequiredSignature),
3538 do_process_instruction(instruction, vec![&mut account_account, &mut owner_account,],)
3539 );
3540
3541 assert_eq!(
3543 Err(TokenError::AuthorityTypeNotSupported.into()),
3544 do_process_instruction(
3545 set_authority(
3546 &program_id,
3547 &account_key,
3548 Some(&owner2_key),
3549 AuthorityType::FreezeAccount,
3550 &owner_key,
3551 &[],
3552 )
3553 .unwrap(),
3554 vec![&mut account_account, &mut owner_account],
3555 )
3556 );
3557
3558 assert_eq!(
3560 Err(TokenError::InvalidInstruction.into()),
3561 do_process_instruction(
3562 set_authority(
3563 &program_id,
3564 &account_key,
3565 None,
3566 AuthorityType::AccountOwner,
3567 &owner_key,
3568 &[],
3569 )
3570 .unwrap(),
3571 vec![&mut account_account, &mut owner_account],
3572 )
3573 );
3574
3575 do_process_instruction(
3577 approve(
3578 &program_id,
3579 &account_key,
3580 &owner2_key,
3581 &owner_key,
3582 &[],
3583 u64::MAX,
3584 )
3585 .unwrap(),
3586 vec![
3587 &mut account_account,
3588 &mut owner2_account,
3589 &mut owner_account,
3590 ],
3591 )
3592 .unwrap();
3593 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3594 assert_eq!(account.delegate, COption::Some(owner2_key));
3595 assert_eq!(account.delegated_amount, u64::MAX);
3596
3597 do_process_instruction(
3599 set_authority(
3600 &program_id,
3601 &account_key,
3602 Some(&owner3_key),
3603 AuthorityType::AccountOwner,
3604 &owner_key,
3605 &[],
3606 )
3607 .unwrap(),
3608 vec![&mut account_account, &mut owner_account],
3609 )
3610 .unwrap();
3611
3612 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3614 assert_eq!(account.delegate, COption::None);
3615 assert_eq!(account.delegated_amount, 0);
3616
3617 do_process_instruction(
3619 set_authority(
3620 &program_id,
3621 &account_key,
3622 Some(&owner2_key),
3623 AuthorityType::AccountOwner,
3624 &owner3_key,
3625 &[],
3626 )
3627 .unwrap(),
3628 vec![&mut account_account, &mut owner3_account],
3629 )
3630 .unwrap();
3631
3632 do_process_instruction(
3634 set_authority(
3635 &program_id,
3636 &account_key,
3637 Some(&owner2_key),
3638 AuthorityType::CloseAccount,
3639 &owner2_key,
3640 &[],
3641 )
3642 .unwrap(),
3643 vec![&mut account_account, &mut owner2_account],
3644 )
3645 .unwrap();
3646
3647 do_process_instruction(
3649 set_authority(
3650 &program_id,
3651 &account_key,
3652 None,
3653 AuthorityType::CloseAccount,
3654 &owner2_key,
3655 &[],
3656 )
3657 .unwrap(),
3658 vec![&mut account_account, &mut owner2_account],
3659 )
3660 .unwrap();
3661
3662 assert_eq!(
3664 Err(TokenError::OwnerMismatch.into()),
3665 do_process_instruction(
3666 set_authority(
3667 &program_id,
3668 &mint_key,
3669 Some(&owner3_key),
3670 AuthorityType::MintTokens,
3671 &owner2_key,
3672 &[]
3673 )
3674 .unwrap(),
3675 vec![&mut mint_account, &mut owner2_account],
3676 )
3677 );
3678
3679 let mut instruction = set_authority(
3681 &program_id,
3682 &mint_key,
3683 Some(&owner2_key),
3684 AuthorityType::MintTokens,
3685 &owner_key,
3686 &[],
3687 )
3688 .unwrap();
3689 instruction.accounts[1].is_signer = false;
3690 assert_eq!(
3691 Err(ProgramError::MissingRequiredSignature),
3692 do_process_instruction(instruction, vec![&mut mint_account, &mut owner_account],)
3693 );
3694
3695 assert_eq!(
3697 Err(TokenError::MintCannotFreeze.into()),
3698 do_process_instruction(
3699 set_authority(
3700 &program_id,
3701 &mint_key,
3702 Some(&owner2_key),
3703 AuthorityType::FreezeAccount,
3704 &owner_key,
3705 &[],
3706 )
3707 .unwrap(),
3708 vec![&mut mint_account, &mut owner_account],
3709 )
3710 );
3711
3712 do_process_instruction(
3714 set_authority(
3715 &program_id,
3716 &mint_key,
3717 Some(&owner2_key),
3718 AuthorityType::MintTokens,
3719 &owner_key,
3720 &[],
3721 )
3722 .unwrap(),
3723 vec![&mut mint_account, &mut owner_account],
3724 )
3725 .unwrap();
3726
3727 do_process_instruction(
3729 set_authority(
3730 &program_id,
3731 &mint_key,
3732 None,
3733 AuthorityType::MintTokens,
3734 &owner2_key,
3735 &[],
3736 )
3737 .unwrap(),
3738 vec![&mut mint_account, &mut owner2_account],
3739 )
3740 .unwrap();
3741
3742 assert_eq!(
3744 Err(TokenError::FixedSupply.into()),
3745 do_process_instruction(
3746 set_authority(
3747 &program_id,
3748 &mint2_key,
3749 Some(&owner2_key),
3750 AuthorityType::MintTokens,
3751 &owner_key,
3752 &[]
3753 )
3754 .unwrap(),
3755 vec![&mut mint_account, &mut owner_account],
3756 )
3757 );
3758
3759 do_process_instruction(
3761 set_authority(
3762 &program_id,
3763 &mint2_key,
3764 Some(&owner2_key),
3765 AuthorityType::FreezeAccount,
3766 &owner_key,
3767 &[],
3768 )
3769 .unwrap(),
3770 vec![&mut mint2_account, &mut owner_account],
3771 )
3772 .unwrap();
3773
3774 do_process_instruction(
3776 set_authority(
3777 &program_id,
3778 &mint2_key,
3779 None,
3780 AuthorityType::FreezeAccount,
3781 &owner2_key,
3782 &[],
3783 )
3784 .unwrap(),
3785 vec![&mut mint2_account, &mut owner2_account],
3786 )
3787 .unwrap();
3788
3789 assert_eq!(
3790 Err(TokenError::MintCannotFreeze.into()),
3791 do_process_instruction(
3792 set_authority(
3793 &program_id,
3794 &mint2_key,
3795 Some(&owner2_key),
3796 AuthorityType::FreezeAccount,
3797 &owner_key,
3798 &[],
3799 )
3800 .unwrap(),
3801 vec![&mut mint2_account, &mut owner2_account],
3802 )
3803 );
3804 }
3805
3806 #[test]
3807 fn test_mint_to_dups() {
3808 let program_id = crate::id();
3809 let account1_key = Pubkey::new_unique();
3810 let mut account1_account = SolanaAccount::new(
3811 account_minimum_balance(),
3812 Account::get_packed_len(),
3813 &program_id,
3814 );
3815 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
3816 let owner_key = Pubkey::new_unique();
3817 let mut owner_account = SolanaAccount::default();
3818 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
3819 let mint_key = Pubkey::new_unique();
3820 let mut mint_account =
3821 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3822 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
3823 let rent_key = rent::id();
3824 let mut rent_sysvar = rent_sysvar();
3825 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
3826
3827 do_process_instruction_dups(
3829 initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
3830 vec![mint_info.clone(), rent_info.clone()],
3831 )
3832 .unwrap();
3833
3834 do_process_instruction_dups(
3836 initialize_account(&program_id, &account1_key, &mint_key, &owner_key).unwrap(),
3837 vec![
3838 account1_info.clone(),
3839 mint_info.clone(),
3840 owner_info.clone(),
3841 rent_info.clone(),
3842 ],
3843 )
3844 .unwrap();
3845
3846 do_process_instruction_dups(
3848 mint_to(&program_id, &mint_key, &account1_key, &mint_key, &[], 42).unwrap(),
3849 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
3850 )
3851 .unwrap();
3852
3853 do_process_instruction_dups(
3855 mint_to_checked(&program_id, &mint_key, &account1_key, &mint_key, &[], 42, 2).unwrap(),
3856 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
3857 )
3858 .unwrap();
3859
3860 let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow()).unwrap();
3862 mint.mint_authority = COption::Some(account1_key);
3863 Mint::pack(mint, &mut mint_info.data.borrow_mut()).unwrap();
3864 do_process_instruction_dups(
3865 mint_to(
3866 &program_id,
3867 &mint_key,
3868 &account1_key,
3869 &account1_key,
3870 &[],
3871 42,
3872 )
3873 .unwrap(),
3874 vec![
3875 mint_info.clone(),
3876 account1_info.clone(),
3877 account1_info.clone(),
3878 ],
3879 )
3880 .unwrap();
3881
3882 do_process_instruction_dups(
3884 mint_to(
3885 &program_id,
3886 &mint_key,
3887 &account1_key,
3888 &account1_key,
3889 &[],
3890 42,
3891 )
3892 .unwrap(),
3893 vec![
3894 mint_info.clone(),
3895 account1_info.clone(),
3896 account1_info.clone(),
3897 ],
3898 )
3899 .unwrap();
3900 }
3901
3902 #[test]
3903 fn test_mint_to() {
3904 let program_id = crate::id();
3905 let account_key = Pubkey::new_unique();
3906 let mut account_account = SolanaAccount::new(
3907 account_minimum_balance(),
3908 Account::get_packed_len(),
3909 &program_id,
3910 );
3911 let account2_key = Pubkey::new_unique();
3912 let mut account2_account = SolanaAccount::new(
3913 account_minimum_balance(),
3914 Account::get_packed_len(),
3915 &program_id,
3916 );
3917 let account3_key = Pubkey::new_unique();
3918 let mut account3_account = SolanaAccount::new(
3919 account_minimum_balance(),
3920 Account::get_packed_len(),
3921 &program_id,
3922 );
3923 let mismatch_key = Pubkey::new_unique();
3924 let mut mismatch_account = SolanaAccount::new(
3925 account_minimum_balance(),
3926 Account::get_packed_len(),
3927 &program_id,
3928 );
3929 let owner_key = Pubkey::new_unique();
3930 let mut owner_account = SolanaAccount::default();
3931 let owner2_key = Pubkey::new_unique();
3932 let mut owner2_account = SolanaAccount::default();
3933 let mint_key = Pubkey::new_unique();
3934 let mut mint_account =
3935 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3936 let mint2_key = Pubkey::new_unique();
3937 let uninitialized_key = Pubkey::new_unique();
3938 let mut uninitialized_account = SolanaAccount::new(
3939 account_minimum_balance(),
3940 Account::get_packed_len(),
3941 &program_id,
3942 );
3943 let mut rent_sysvar = rent_sysvar();
3944
3945 do_process_instruction(
3947 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3948 vec![&mut mint_account, &mut rent_sysvar],
3949 )
3950 .unwrap();
3951
3952 do_process_instruction(
3954 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3955 vec![
3956 &mut account_account,
3957 &mut mint_account,
3958 &mut owner_account,
3959 &mut rent_sysvar,
3960 ],
3961 )
3962 .unwrap();
3963
3964 do_process_instruction(
3966 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3967 vec![
3968 &mut account2_account,
3969 &mut mint_account,
3970 &mut owner_account,
3971 &mut rent_sysvar,
3972 ],
3973 )
3974 .unwrap();
3975
3976 do_process_instruction(
3978 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
3979 vec![
3980 &mut account3_account,
3981 &mut mint_account,
3982 &mut owner_account,
3983 &mut rent_sysvar,
3984 ],
3985 )
3986 .unwrap();
3987
3988 do_process_instruction(
3990 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
3991 vec![
3992 &mut mismatch_account,
3993 &mut mint_account,
3994 &mut owner_account,
3995 &mut rent_sysvar,
3996 ],
3997 )
3998 .unwrap();
3999 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
4000 account.mint = mint2_key;
4001 Account::pack(account, &mut mismatch_account.data).unwrap();
4002
4003 do_process_instruction(
4005 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
4006 vec![&mut mint_account, &mut account_account, &mut owner_account],
4007 )
4008 .unwrap();
4009
4010 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4011 assert_eq!(mint.supply, 42);
4012 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4013 assert_eq!(account.amount, 42);
4014
4015 do_process_instruction(
4017 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
4018 vec![&mut mint_account, &mut account2_account, &mut owner_account],
4019 )
4020 .unwrap();
4021
4022 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4023 assert_eq!(mint.supply, 84);
4024 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
4025 assert_eq!(account.amount, 42);
4026
4027 let mut instruction =
4029 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
4030 instruction.accounts[2].is_signer = false;
4031 assert_eq!(
4032 Err(ProgramError::MissingRequiredSignature),
4033 do_process_instruction(
4034 instruction,
4035 vec![&mut mint_account, &mut account2_account, &mut owner_account],
4036 )
4037 );
4038
4039 assert_eq!(
4041 Err(TokenError::MintMismatch.into()),
4042 do_process_instruction(
4043 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
4044 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
4045 )
4046 );
4047
4048 assert_eq!(
4050 Err(TokenError::OwnerMismatch.into()),
4051 do_process_instruction(
4052 mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
4053 vec![
4054 &mut mint_account,
4055 &mut account2_account,
4056 &mut owner2_account,
4057 ],
4058 )
4059 );
4060
4061 let not_program_id = Pubkey::new_unique();
4063 mint_account.owner = not_program_id;
4064 assert_eq!(
4065 Err(ProgramError::IncorrectProgramId),
4066 do_process_instruction(
4067 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
4068 vec![&mut mint_account, &mut account_account, &mut owner_account],
4069 )
4070 );
4071 mint_account.owner = program_id;
4072
4073 let not_program_id = Pubkey::new_unique();
4075 account_account.owner = not_program_id;
4076 assert_eq!(
4077 Err(ProgramError::IncorrectProgramId),
4078 do_process_instruction(
4079 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
4080 vec![&mut mint_account, &mut account_account, &mut owner_account],
4081 )
4082 );
4083 account_account.owner = program_id;
4084
4085 assert_eq!(
4087 Err(ProgramError::UninitializedAccount),
4088 do_process_instruction(
4089 mint_to(
4090 &program_id,
4091 &mint_key,
4092 &uninitialized_key,
4093 &owner_key,
4094 &[],
4095 42
4096 )
4097 .unwrap(),
4098 vec![
4099 &mut mint_account,
4100 &mut uninitialized_account,
4101 &mut owner_account,
4102 ],
4103 )
4104 );
4105
4106 do_process_instruction(
4108 set_authority(
4109 &program_id,
4110 &mint_key,
4111 None,
4112 AuthorityType::MintTokens,
4113 &owner_key,
4114 &[],
4115 )
4116 .unwrap(),
4117 vec![&mut mint_account, &mut owner_account],
4118 )
4119 .unwrap();
4120 assert_eq!(
4121 Err(TokenError::FixedSupply.into()),
4122 do_process_instruction(
4123 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
4124 vec![&mut mint_account, &mut account2_account, &mut owner_account],
4125 )
4126 );
4127 }
4128
4129 #[test]
4130 fn test_burn_dups() {
4131 let program_id = crate::id();
4132 let account1_key = Pubkey::new_unique();
4133 let mut account1_account = SolanaAccount::new(
4134 account_minimum_balance(),
4135 Account::get_packed_len(),
4136 &program_id,
4137 );
4138 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
4139 let owner_key = Pubkey::new_unique();
4140 let mut owner_account = SolanaAccount::default();
4141 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
4142 let mint_key = Pubkey::new_unique();
4143 let mut mint_account =
4144 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4145 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
4146 let rent_key = rent::id();
4147 let mut rent_sysvar = rent_sysvar();
4148 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
4149
4150 do_process_instruction_dups(
4152 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4153 vec![mint_info.clone(), rent_info.clone()],
4154 )
4155 .unwrap();
4156
4157 do_process_instruction_dups(
4159 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
4160 vec![
4161 account1_info.clone(),
4162 mint_info.clone(),
4163 account1_info.clone(),
4164 rent_info.clone(),
4165 ],
4166 )
4167 .unwrap();
4168
4169 do_process_instruction_dups(
4171 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4172 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4173 )
4174 .unwrap();
4175
4176 do_process_instruction_dups(
4178 burn(
4179 &program_id,
4180 &mint_key,
4181 &account1_key,
4182 &account1_key,
4183 &[],
4184 500,
4185 )
4186 .unwrap(),
4187 vec![
4188 account1_info.clone(),
4189 mint_info.clone(),
4190 account1_info.clone(),
4191 ],
4192 )
4193 .unwrap();
4194
4195 do_process_instruction_dups(
4197 burn_checked(
4198 &program_id,
4199 &account1_key,
4200 &mint_key,
4201 &account1_key,
4202 &[],
4203 500,
4204 2,
4205 )
4206 .unwrap(),
4207 vec![
4208 account1_info.clone(),
4209 mint_info.clone(),
4210 account1_info.clone(),
4211 ],
4212 )
4213 .unwrap();
4214
4215 do_process_instruction_dups(
4217 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4218 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4219 )
4220 .unwrap();
4221 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4222 account.owner = mint_key;
4223 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4224 do_process_instruction_dups(
4225 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
4226 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4227 )
4228 .unwrap();
4229
4230 do_process_instruction_dups(
4232 burn_checked(
4233 &program_id,
4234 &account1_key,
4235 &mint_key,
4236 &mint_key,
4237 &[],
4238 500,
4239 2,
4240 )
4241 .unwrap(),
4242 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4243 )
4244 .unwrap();
4245
4246 do_process_instruction_dups(
4248 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4249 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4250 )
4251 .unwrap();
4252 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4253 account.delegated_amount = 1000;
4254 account.delegate = COption::Some(account1_key);
4255 account.owner = owner_key;
4256 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4257 do_process_instruction_dups(
4258 burn(
4259 &program_id,
4260 &account1_key,
4261 &mint_key,
4262 &account1_key,
4263 &[],
4264 500,
4265 )
4266 .unwrap(),
4267 vec![
4268 account1_info.clone(),
4269 mint_info.clone(),
4270 account1_info.clone(),
4271 ],
4272 )
4273 .unwrap();
4274
4275 do_process_instruction_dups(
4277 burn_checked(
4278 &program_id,
4279 &account1_key,
4280 &mint_key,
4281 &account1_key,
4282 &[],
4283 500,
4284 2,
4285 )
4286 .unwrap(),
4287 vec![
4288 account1_info.clone(),
4289 mint_info.clone(),
4290 account1_info.clone(),
4291 ],
4292 )
4293 .unwrap();
4294
4295 do_process_instruction_dups(
4297 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4298 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4299 )
4300 .unwrap();
4301 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4302 account.delegated_amount = 1000;
4303 account.delegate = COption::Some(mint_key);
4304 account.owner = owner_key;
4305 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4306 do_process_instruction_dups(
4307 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
4308 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4309 )
4310 .unwrap();
4311
4312 do_process_instruction_dups(
4314 burn_checked(
4315 &program_id,
4316 &account1_key,
4317 &mint_key,
4318 &mint_key,
4319 &[],
4320 500,
4321 2,
4322 )
4323 .unwrap(),
4324 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4325 )
4326 .unwrap();
4327 }
4328
4329 #[test]
4330 fn test_burn() {
4331 let program_id = crate::id();
4332 let account_key = Pubkey::new_unique();
4333 let mut account_account = SolanaAccount::new(
4334 account_minimum_balance(),
4335 Account::get_packed_len(),
4336 &program_id,
4337 );
4338 let account2_key = Pubkey::new_unique();
4339 let mut account2_account = SolanaAccount::new(
4340 account_minimum_balance(),
4341 Account::get_packed_len(),
4342 &program_id,
4343 );
4344 let account3_key = Pubkey::new_unique();
4345 let mut account3_account = SolanaAccount::new(
4346 account_minimum_balance(),
4347 Account::get_packed_len(),
4348 &program_id,
4349 );
4350 let delegate_key = Pubkey::new_unique();
4351 let mut delegate_account = SolanaAccount::default();
4352 let mismatch_key = Pubkey::new_unique();
4353 let mut mismatch_account = SolanaAccount::new(
4354 account_minimum_balance(),
4355 Account::get_packed_len(),
4356 &program_id,
4357 );
4358 let owner_key = Pubkey::new_unique();
4359 let mut owner_account = SolanaAccount::default();
4360 let owner2_key = Pubkey::new_unique();
4361 let mut owner2_account = SolanaAccount::default();
4362 let mint_key = Pubkey::new_unique();
4363 let mut mint_account =
4364 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4365 let mint2_key = Pubkey::new_unique();
4366 let mut rent_sysvar = rent_sysvar();
4367
4368 do_process_instruction(
4370 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4371 vec![&mut mint_account, &mut rent_sysvar],
4372 )
4373 .unwrap();
4374
4375 do_process_instruction(
4377 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4378 vec![
4379 &mut account_account,
4380 &mut mint_account,
4381 &mut owner_account,
4382 &mut rent_sysvar,
4383 ],
4384 )
4385 .unwrap();
4386
4387 do_process_instruction(
4389 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
4390 vec![
4391 &mut account2_account,
4392 &mut mint_account,
4393 &mut owner_account,
4394 &mut rent_sysvar,
4395 ],
4396 )
4397 .unwrap();
4398
4399 do_process_instruction(
4401 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
4402 vec![
4403 &mut account3_account,
4404 &mut mint_account,
4405 &mut owner_account,
4406 &mut rent_sysvar,
4407 ],
4408 )
4409 .unwrap();
4410
4411 do_process_instruction(
4413 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
4414 vec![
4415 &mut mismatch_account,
4416 &mut mint_account,
4417 &mut owner_account,
4418 &mut rent_sysvar,
4419 ],
4420 )
4421 .unwrap();
4422
4423 do_process_instruction(
4425 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
4426 vec![&mut mint_account, &mut account_account, &mut owner_account],
4427 )
4428 .unwrap();
4429
4430 do_process_instruction(
4432 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 1000).unwrap(),
4433 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
4434 )
4435 .unwrap();
4436 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
4437 account.mint = mint2_key;
4438 Account::pack(account, &mut mismatch_account.data).unwrap();
4439
4440 let mut instruction =
4442 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
4443 instruction.accounts[1].is_signer = false;
4444 assert_eq!(
4445 Err(TokenError::OwnerMismatch.into()),
4446 do_process_instruction(
4447 instruction,
4448 vec![
4449 &mut account_account,
4450 &mut mint_account,
4451 &mut delegate_account
4452 ],
4453 )
4454 );
4455
4456 assert_eq!(
4458 Err(TokenError::OwnerMismatch.into()),
4459 do_process_instruction(
4460 burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
4461 vec![&mut account_account, &mut mint_account, &mut owner2_account],
4462 )
4463 );
4464
4465 let not_program_id = Pubkey::new_unique();
4467 account_account.owner = not_program_id;
4468 assert_eq!(
4469 Err(ProgramError::IncorrectProgramId),
4470 do_process_instruction(
4471 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
4472 vec![&mut account_account, &mut mint_account, &mut owner_account],
4473 )
4474 );
4475 account_account.owner = program_id;
4476
4477 let not_program_id = Pubkey::new_unique();
4479 mint_account.owner = not_program_id;
4480 assert_eq!(
4481 Err(ProgramError::IncorrectProgramId),
4482 do_process_instruction(
4483 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
4484 vec![&mut account_account, &mut mint_account, &mut owner_account],
4485 )
4486 );
4487 mint_account.owner = program_id;
4488
4489 assert_eq!(
4491 Err(TokenError::MintMismatch.into()),
4492 do_process_instruction(
4493 burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
4494 vec![&mut mismatch_account, &mut mint_account, &mut owner_account],
4495 )
4496 );
4497
4498 do_process_instruction(
4500 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 21).unwrap(),
4501 vec![&mut account_account, &mut mint_account, &mut owner_account],
4502 )
4503 .unwrap();
4504
4505 assert_eq!(
4507 Err(TokenError::MintDecimalsMismatch.into()),
4508 do_process_instruction(
4509 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 3).unwrap(),
4510 vec![&mut account_account, &mut mint_account, &mut owner_account],
4511 )
4512 );
4513
4514 do_process_instruction(
4516 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 2).unwrap(),
4517 vec![&mut account_account, &mut mint_account, &mut owner_account],
4518 )
4519 .unwrap();
4520
4521 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4522 assert_eq!(mint.supply, 2000 - 42);
4523 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4524 assert_eq!(account.amount, 1000 - 42);
4525
4526 assert_eq!(
4528 Err(TokenError::InsufficientFunds.into()),
4529 do_process_instruction(
4530 burn(
4531 &program_id,
4532 &account_key,
4533 &mint_key,
4534 &owner_key,
4535 &[],
4536 100_000_000
4537 )
4538 .unwrap(),
4539 vec![&mut account_account, &mut mint_account, &mut owner_account],
4540 )
4541 );
4542
4543 do_process_instruction(
4545 approve(
4546 &program_id,
4547 &account_key,
4548 &delegate_key,
4549 &owner_key,
4550 &[],
4551 84,
4552 )
4553 .unwrap(),
4554 vec![
4555 &mut account_account,
4556 &mut delegate_account,
4557 &mut owner_account,
4558 ],
4559 )
4560 .unwrap();
4561
4562 assert_eq!(
4564 Err(TokenError::OwnerMismatch.into()),
4565 do_process_instruction(
4566 burn(
4567 &program_id,
4568 &account_key,
4569 &mint_key,
4570 &owner2_key, &[],
4572 1,
4573 )
4574 .unwrap(),
4575 vec![&mut account_account, &mut mint_account, &mut owner2_account],
4576 )
4577 );
4578
4579 assert_eq!(
4581 Err(TokenError::InsufficientFunds.into()),
4582 do_process_instruction(
4583 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 85).unwrap(),
4584 vec![
4585 &mut account_account,
4586 &mut mint_account,
4587 &mut delegate_account
4588 ],
4589 )
4590 );
4591
4592 do_process_instruction(
4594 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
4595 vec![
4596 &mut account_account,
4597 &mut mint_account,
4598 &mut delegate_account,
4599 ],
4600 )
4601 .unwrap();
4602
4603 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4605 assert_eq!(mint.supply, 2000 - 42 - 84);
4606 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4607 assert_eq!(account.amount, 1000 - 42 - 84);
4608
4609 assert_eq!(
4611 Err(TokenError::OwnerMismatch.into()),
4612 do_process_instruction(
4613 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 1).unwrap(),
4614 vec![
4615 &mut account_account,
4616 &mut mint_account,
4617 &mut delegate_account
4618 ],
4619 )
4620 );
4621 }
4622
4623 #[test]
4624 fn test_burn_and_close_system_and_incinerator_tokens() {
4625 let program_id = crate::id();
4626 let account_key = Pubkey::new_unique();
4627 let mut account_account = SolanaAccount::new(
4628 account_minimum_balance(),
4629 Account::get_packed_len(),
4630 &program_id,
4631 );
4632 let incinerator_account_key = Pubkey::new_unique();
4633 let mut incinerator_account = SolanaAccount::new(
4634 account_minimum_balance(),
4635 Account::get_packed_len(),
4636 &program_id,
4637 );
4638 let system_account_key = Pubkey::new_unique();
4639 let mut system_account = SolanaAccount::new(
4640 account_minimum_balance(),
4641 Account::get_packed_len(),
4642 &program_id,
4643 );
4644 let owner_key = Pubkey::new_unique();
4645 let mut owner_account = SolanaAccount::default();
4646 let recipient_key = Pubkey::new_unique();
4647 let mut recipient_account = SolanaAccount::default();
4648 let mut mock_incinerator_account = SolanaAccount::default();
4649 let mint_key = Pubkey::new_unique();
4650 let mut mint_account =
4651 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4652
4653 do_process_instruction(
4655 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4656 vec![&mut mint_account],
4657 )
4658 .unwrap();
4659
4660 do_process_instruction(
4662 initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4663 vec![&mut account_account, &mut mint_account],
4664 )
4665 .unwrap();
4666
4667 do_process_instruction(
4669 initialize_account3(
4670 &program_id,
4671 &incinerator_account_key,
4672 &mint_key,
4673 &solana_program::incinerator::id(),
4674 )
4675 .unwrap(),
4676 vec![&mut incinerator_account, &mut mint_account],
4677 )
4678 .unwrap();
4679 do_process_instruction(
4680 initialize_account3(
4681 &program_id,
4682 &system_account_key,
4683 &mint_key,
4684 &solana_program::system_program::id(),
4685 )
4686 .unwrap(),
4687 vec![&mut system_account, &mut mint_account],
4688 )
4689 .unwrap();
4690
4691 do_process_instruction(
4693 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
4694 vec![&mut mint_account, &mut account_account, &mut owner_account],
4695 )
4696 .unwrap();
4697
4698 do_process_instruction(
4700 transfer(
4701 &program_id,
4702 &account_key,
4703 &incinerator_account_key,
4704 &owner_key,
4705 &[],
4706 500,
4707 )
4708 .unwrap(),
4709 vec![
4710 &mut account_account,
4711 &mut incinerator_account,
4712 &mut owner_account,
4713 ],
4714 )
4715 .unwrap();
4716 do_process_instruction(
4717 transfer(
4718 &program_id,
4719 &account_key,
4720 &system_account_key,
4721 &owner_key,
4722 &[],
4723 500,
4724 )
4725 .unwrap(),
4726 vec![
4727 &mut account_account,
4728 &mut system_account,
4729 &mut owner_account,
4730 ],
4731 )
4732 .unwrap();
4733
4734 assert_eq!(
4736 Err(TokenError::NonNativeHasBalance.into()),
4737 do_process_instruction(
4738 close_account(
4739 &program_id,
4740 &incinerator_account_key,
4741 &solana_program::incinerator::id(),
4742 &owner_key,
4743 &[]
4744 )
4745 .unwrap(),
4746 vec![
4747 &mut incinerator_account,
4748 &mut mock_incinerator_account,
4749 &mut owner_account,
4750 ],
4751 )
4752 );
4753 assert_eq!(
4754 Err(TokenError::NonNativeHasBalance.into()),
4755 do_process_instruction(
4756 close_account(
4757 &program_id,
4758 &system_account_key,
4759 &solana_program::incinerator::id(),
4760 &owner_key,
4761 &[]
4762 )
4763 .unwrap(),
4764 vec![
4765 &mut system_account,
4766 &mut mock_incinerator_account,
4767 &mut owner_account,
4768 ],
4769 )
4770 );
4771
4772 do_process_instruction(
4774 burn(
4775 &program_id,
4776 &incinerator_account_key,
4777 &mint_key,
4778 &recipient_key,
4779 &[],
4780 500,
4781 )
4782 .unwrap(),
4783 vec![
4784 &mut incinerator_account,
4785 &mut mint_account,
4786 &mut recipient_account,
4787 ],
4788 )
4789 .unwrap();
4790 do_process_instruction(
4791 burn(
4792 &program_id,
4793 &system_account_key,
4794 &mint_key,
4795 &recipient_key,
4796 &[],
4797 500,
4798 )
4799 .unwrap(),
4800 vec![
4801 &mut system_account,
4802 &mut mint_account,
4803 &mut recipient_account,
4804 ],
4805 )
4806 .unwrap();
4807
4808 assert_eq!(
4810 Err(ProgramError::InvalidAccountData),
4811 do_process_instruction(
4812 close_account(
4813 &program_id,
4814 &incinerator_account_key,
4815 &recipient_key,
4816 &owner_key,
4817 &[]
4818 )
4819 .unwrap(),
4820 vec![
4821 &mut incinerator_account,
4822 &mut recipient_account,
4823 &mut owner_account,
4824 ],
4825 )
4826 );
4827 assert_eq!(
4828 Err(ProgramError::InvalidAccountData),
4829 do_process_instruction(
4830 close_account(
4831 &program_id,
4832 &system_account_key,
4833 &recipient_key,
4834 &owner_key,
4835 &[]
4836 )
4837 .unwrap(),
4838 vec![
4839 &mut system_account,
4840 &mut recipient_account,
4841 &mut owner_account,
4842 ],
4843 )
4844 );
4845
4846 do_process_instruction(
4848 close_account(
4849 &program_id,
4850 &incinerator_account_key,
4851 &solana_program::incinerator::id(),
4852 &owner_key,
4853 &[],
4854 )
4855 .unwrap(),
4856 vec![
4857 &mut incinerator_account,
4858 &mut mock_incinerator_account,
4859 &mut owner_account,
4860 ],
4861 )
4862 .unwrap();
4863
4864 do_process_instruction(
4865 close_account(
4866 &program_id,
4867 &system_account_key,
4868 &solana_program::incinerator::id(),
4869 &owner_key,
4870 &[],
4871 )
4872 .unwrap(),
4873 vec![
4874 &mut system_account,
4875 &mut mock_incinerator_account,
4876 &mut owner_account,
4877 ],
4878 )
4879 .unwrap();
4880 }
4881
4882 #[test]
4883 fn test_multisig() {
4884 let program_id = crate::id();
4885 let mint_key = Pubkey::new_unique();
4886 let mut mint_account =
4887 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4888 let account_key = Pubkey::new_unique();
4889 let mut account = SolanaAccount::new(
4890 account_minimum_balance(),
4891 Account::get_packed_len(),
4892 &program_id,
4893 );
4894 let account2_key = Pubkey::new_unique();
4895 let mut account2_account = SolanaAccount::new(
4896 account_minimum_balance(),
4897 Account::get_packed_len(),
4898 &program_id,
4899 );
4900 let owner_key = Pubkey::new_unique();
4901 let mut owner_account = SolanaAccount::default();
4902 let multisig_key = Pubkey::new_unique();
4903 let mut multisig_account = SolanaAccount::new(42, Multisig::get_packed_len(), &program_id);
4904 let multisig_delegate_key = Pubkey::new_unique();
4905 let mut multisig_delegate_account = SolanaAccount::new(
4906 multisig_minimum_balance(),
4907 Multisig::get_packed_len(),
4908 &program_id,
4909 );
4910 let signer_keys = vec![Pubkey::new_unique(); MAX_SIGNERS];
4911 let signer_key_refs: Vec<&Pubkey> = signer_keys.iter().collect();
4912 let mut signer_accounts = vec![SolanaAccount::new(0, 0, &program_id); MAX_SIGNERS];
4913 let mut rent_sysvar = rent_sysvar();
4914
4915 let account_info_iter = &mut signer_accounts.iter_mut();
4917 assert_eq!(
4918 Err(TokenError::NotRentExempt.into()),
4919 do_process_instruction(
4920 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
4921 vec![
4922 &mut multisig_account,
4923 &mut rent_sysvar,
4924 account_info_iter.next().unwrap(),
4925 ],
4926 )
4927 );
4928
4929 multisig_account.lamports = multisig_minimum_balance();
4930 let mut multisig_account2 = multisig_account.clone();
4931
4932 let account_info_iter = &mut signer_accounts.iter_mut();
4934 do_process_instruction(
4935 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
4936 vec![
4937 &mut multisig_account,
4938 &mut rent_sysvar,
4939 account_info_iter.next().unwrap(),
4940 ],
4941 )
4942 .unwrap();
4943
4944 let account_info_iter = &mut signer_accounts.iter_mut();
4946 do_process_instruction(
4947 initialize_multisig2(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
4948 vec![&mut multisig_account2, account_info_iter.next().unwrap()],
4949 )
4950 .unwrap();
4951
4952 let account_info_iter = &mut signer_accounts.iter_mut();
4954 do_process_instruction(
4955 initialize_multisig(
4956 &program_id,
4957 &multisig_delegate_key,
4958 &signer_key_refs,
4959 MAX_SIGNERS as u8,
4960 )
4961 .unwrap(),
4962 vec![
4963 &mut multisig_delegate_account,
4964 &mut rent_sysvar,
4965 account_info_iter.next().unwrap(),
4966 account_info_iter.next().unwrap(),
4967 account_info_iter.next().unwrap(),
4968 account_info_iter.next().unwrap(),
4969 account_info_iter.next().unwrap(),
4970 account_info_iter.next().unwrap(),
4971 account_info_iter.next().unwrap(),
4972 account_info_iter.next().unwrap(),
4973 account_info_iter.next().unwrap(),
4974 account_info_iter.next().unwrap(),
4975 account_info_iter.next().unwrap(),
4976 ],
4977 )
4978 .unwrap();
4979
4980 do_process_instruction(
4982 initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
4983 vec![&mut mint_account, &mut rent_sysvar],
4984 )
4985 .unwrap();
4986
4987 do_process_instruction(
4989 initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
4990 vec![
4991 &mut account,
4992 &mut mint_account,
4993 &mut multisig_account,
4994 &mut rent_sysvar,
4995 ],
4996 )
4997 .unwrap();
4998
4999 do_process_instruction(
5001 initialize_account(
5002 &program_id,
5003 &account2_key,
5004 &mint_key,
5005 &multisig_delegate_key,
5006 )
5007 .unwrap(),
5008 vec![
5009 &mut account2_account,
5010 &mut mint_account,
5011 &mut multisig_account,
5012 &mut rent_sysvar,
5013 ],
5014 )
5015 .unwrap();
5016
5017 let account_info_iter = &mut signer_accounts.iter_mut();
5019 do_process_instruction(
5020 mint_to(
5021 &program_id,
5022 &mint_key,
5023 &account_key,
5024 &multisig_key,
5025 &[&signer_keys[0]],
5026 1000,
5027 )
5028 .unwrap(),
5029 vec![
5030 &mut mint_account,
5031 &mut account,
5032 &mut multisig_account,
5033 account_info_iter.next().unwrap(),
5034 ],
5035 )
5036 .unwrap();
5037
5038 let account_info_iter = &mut signer_accounts.iter_mut();
5040 do_process_instruction(
5041 approve(
5042 &program_id,
5043 &account_key,
5044 &multisig_delegate_key,
5045 &multisig_key,
5046 &[&signer_keys[0]],
5047 100,
5048 )
5049 .unwrap(),
5050 vec![
5051 &mut account,
5052 &mut multisig_delegate_account,
5053 &mut multisig_account,
5054 account_info_iter.next().unwrap(),
5055 ],
5056 )
5057 .unwrap();
5058
5059 let account_info_iter = &mut signer_accounts.iter_mut();
5061 do_process_instruction(
5062 transfer(
5063 &program_id,
5064 &account_key,
5065 &account2_key,
5066 &multisig_key,
5067 &[&signer_keys[0]],
5068 42,
5069 )
5070 .unwrap(),
5071 vec![
5072 &mut account,
5073 &mut account2_account,
5074 &mut multisig_account,
5075 account_info_iter.next().unwrap(),
5076 ],
5077 )
5078 .unwrap();
5079
5080 let account_info_iter = &mut signer_accounts.iter_mut();
5082 do_process_instruction(
5083 transfer(
5084 &program_id,
5085 &account_key,
5086 &account2_key,
5087 &multisig_delegate_key,
5088 &signer_key_refs,
5089 42,
5090 )
5091 .unwrap(),
5092 vec![
5093 &mut account,
5094 &mut account2_account,
5095 &mut multisig_delegate_account,
5096 account_info_iter.next().unwrap(),
5097 account_info_iter.next().unwrap(),
5098 account_info_iter.next().unwrap(),
5099 account_info_iter.next().unwrap(),
5100 account_info_iter.next().unwrap(),
5101 account_info_iter.next().unwrap(),
5102 account_info_iter.next().unwrap(),
5103 account_info_iter.next().unwrap(),
5104 account_info_iter.next().unwrap(),
5105 account_info_iter.next().unwrap(),
5106 account_info_iter.next().unwrap(),
5107 ],
5108 )
5109 .unwrap();
5110
5111 let account_info_iter = &mut signer_accounts.iter_mut();
5113 do_process_instruction(
5114 mint_to(
5115 &program_id,
5116 &mint_key,
5117 &account2_key,
5118 &multisig_key,
5119 &[&signer_keys[0]],
5120 42,
5121 )
5122 .unwrap(),
5123 vec![
5124 &mut mint_account,
5125 &mut account2_account,
5126 &mut multisig_account,
5127 account_info_iter.next().unwrap(),
5128 ],
5129 )
5130 .unwrap();
5131
5132 let account_info_iter = &mut signer_accounts.iter_mut();
5134 do_process_instruction(
5135 burn(
5136 &program_id,
5137 &account_key,
5138 &mint_key,
5139 &multisig_key,
5140 &[&signer_keys[0]],
5141 42,
5142 )
5143 .unwrap(),
5144 vec![
5145 &mut account,
5146 &mut mint_account,
5147 &mut multisig_account,
5148 account_info_iter.next().unwrap(),
5149 ],
5150 )
5151 .unwrap();
5152
5153 let account_info_iter = &mut signer_accounts.iter_mut();
5155 do_process_instruction(
5156 burn(
5157 &program_id,
5158 &account_key,
5159 &mint_key,
5160 &multisig_delegate_key,
5161 &signer_key_refs,
5162 42,
5163 )
5164 .unwrap(),
5165 vec![
5166 &mut account,
5167 &mut mint_account,
5168 &mut multisig_delegate_account,
5169 account_info_iter.next().unwrap(),
5170 account_info_iter.next().unwrap(),
5171 account_info_iter.next().unwrap(),
5172 account_info_iter.next().unwrap(),
5173 account_info_iter.next().unwrap(),
5174 account_info_iter.next().unwrap(),
5175 account_info_iter.next().unwrap(),
5176 account_info_iter.next().unwrap(),
5177 account_info_iter.next().unwrap(),
5178 account_info_iter.next().unwrap(),
5179 account_info_iter.next().unwrap(),
5180 ],
5181 )
5182 .unwrap();
5183
5184 let account3_key = Pubkey::new_unique();
5186 let mut account3_account = SolanaAccount::new(
5187 account_minimum_balance(),
5188 Account::get_packed_len(),
5189 &program_id,
5190 );
5191 let mint2_key = Pubkey::new_unique();
5192 let mut mint2_account =
5193 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5194 do_process_instruction(
5195 initialize_mint(
5196 &program_id,
5197 &mint2_key,
5198 &multisig_key,
5199 Some(&multisig_key),
5200 2,
5201 )
5202 .unwrap(),
5203 vec![&mut mint2_account, &mut rent_sysvar],
5204 )
5205 .unwrap();
5206 do_process_instruction(
5207 initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
5208 vec![
5209 &mut account3_account,
5210 &mut mint2_account,
5211 &mut owner_account,
5212 &mut rent_sysvar,
5213 ],
5214 )
5215 .unwrap();
5216 let account_info_iter = &mut signer_accounts.iter_mut();
5217 do_process_instruction(
5218 mint_to(
5219 &program_id,
5220 &mint2_key,
5221 &account3_key,
5222 &multisig_key,
5223 &[&signer_keys[0]],
5224 1000,
5225 )
5226 .unwrap(),
5227 vec![
5228 &mut mint2_account,
5229 &mut account3_account,
5230 &mut multisig_account,
5231 account_info_iter.next().unwrap(),
5232 ],
5233 )
5234 .unwrap();
5235 let account_info_iter = &mut signer_accounts.iter_mut();
5236 do_process_instruction(
5237 freeze_account(
5238 &program_id,
5239 &account3_key,
5240 &mint2_key,
5241 &multisig_key,
5242 &[&signer_keys[0]],
5243 )
5244 .unwrap(),
5245 vec![
5246 &mut account3_account,
5247 &mut mint2_account,
5248 &mut multisig_account,
5249 account_info_iter.next().unwrap(),
5250 ],
5251 )
5252 .unwrap();
5253
5254 let account_info_iter = &mut signer_accounts.iter_mut();
5256 do_process_instruction(
5257 set_authority(
5258 &program_id,
5259 &mint_key,
5260 Some(&owner_key),
5261 AuthorityType::MintTokens,
5262 &multisig_key,
5263 &[&signer_keys[0]],
5264 )
5265 .unwrap(),
5266 vec![
5267 &mut mint_account,
5268 &mut multisig_account,
5269 account_info_iter.next().unwrap(),
5270 ],
5271 )
5272 .unwrap();
5273
5274 let account_info_iter = &mut signer_accounts.iter_mut();
5276 do_process_instruction(
5277 set_authority(
5278 &program_id,
5279 &account_key,
5280 Some(&owner_key),
5281 AuthorityType::AccountOwner,
5282 &multisig_key,
5283 &[&signer_keys[0]],
5284 )
5285 .unwrap(),
5286 vec![
5287 &mut account,
5288 &mut multisig_account,
5289 account_info_iter.next().unwrap(),
5290 ],
5291 )
5292 .unwrap();
5293 }
5294
5295 #[test]
5296 fn test_validate_owner() {
5297 let program_id = crate::id();
5298 let owner_key = Pubkey::new_unique();
5299 let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
5300 for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
5301 *signer_key = Pubkey::new_unique();
5302 }
5303 let mut signer_lamports = 0;
5304 let mut signer_data = vec![];
5305 let mut signers = vec![
5306 AccountInfo::new(
5307 &owner_key,
5308 true,
5309 false,
5310 &mut signer_lamports,
5311 &mut signer_data,
5312 &program_id,
5313 false,
5314 Epoch::default(),
5315 );
5316 MAX_SIGNERS + 1
5317 ];
5318 for (signer, key) in signers.iter_mut().zip(&signer_keys) {
5319 signer.key = key;
5320 }
5321 let mut lamports = 0;
5322 let mut data = vec![0; Multisig::get_packed_len()];
5323 let mut multisig = Multisig::unpack_unchecked(&data).unwrap();
5324 multisig.m = MAX_SIGNERS as u8;
5325 multisig.n = MAX_SIGNERS as u8;
5326 multisig.signers = signer_keys;
5327 multisig.is_initialized = true;
5328 Multisig::pack(multisig, &mut data).unwrap();
5329 let owner_account_info = AccountInfo::new(
5330 &owner_key,
5331 false,
5332 false,
5333 &mut lamports,
5334 &mut data,
5335 &program_id,
5336 false,
5337 Epoch::default(),
5338 );
5339
5340 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
5342
5343 {
5345 let mut multisig =
5346 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5347 multisig.m = 1;
5348 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5349 }
5350 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
5351
5352 {
5354 let mut multisig =
5355 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5356 multisig.m = 2;
5357 multisig.n = 1;
5358 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5359 }
5360 assert_eq!(
5361 Err(ProgramError::MissingRequiredSignature),
5362 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
5363 );
5364
5365 {
5367 let mut multisig =
5368 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5369 multisig.m = 0;
5370 multisig.n = 11;
5371 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5372 }
5373 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
5374
5375 {
5377 let mut multisig =
5378 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5379 multisig.m = 2;
5380 multisig.n = 11;
5381 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5382 }
5383 assert_eq!(
5384 Err(ProgramError::MissingRequiredSignature),
5385 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &[])
5386 );
5387 {
5389 let mut multisig =
5390 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5391 multisig.m = 2;
5392 multisig.n = 11;
5393 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5394 }
5395 assert_eq!(
5396 Err(ProgramError::MissingRequiredSignature),
5397 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[0..1])
5398 );
5399
5400 {
5402 let mut multisig =
5403 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5404 multisig.m = 2;
5405 multisig.n = 11;
5406 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5407 }
5408 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[5..7])
5409 .unwrap();
5410
5411 {
5413 let mut multisig =
5414 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5415 multisig.m = 11;
5416 multisig.n = 11;
5417 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5418 }
5419 signers[5].is_signer = false;
5420 assert_eq!(
5421 Err(ProgramError::MissingRequiredSignature),
5422 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
5423 );
5424 signers[5].is_signer = true;
5425
5426 {
5428 let mut signer_lamports = 0;
5429 let mut signer_data = vec![];
5430 let signers = vec![
5431 AccountInfo::new(
5432 &signer_keys[5],
5433 true,
5434 false,
5435 &mut signer_lamports,
5436 &mut signer_data,
5437 &program_id,
5438 false,
5439 Epoch::default(),
5440 );
5441 MAX_SIGNERS + 1
5442 ];
5443 let mut multisig =
5444 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5445 multisig.m = 11;
5446 multisig.n = 11;
5447 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5448 assert_eq!(
5449 Err(ProgramError::MissingRequiredSignature),
5450 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
5451 );
5452 }
5453 }
5454
5455 #[test]
5456 fn test_owner_close_account_dups() {
5457 let program_id = crate::id();
5458 let owner_key = Pubkey::new_unique();
5459 let mint_key = Pubkey::new_unique();
5460 let mut mint_account =
5461 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5462 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
5463 let rent_key = rent::id();
5464 let mut rent_sysvar = rent_sysvar();
5465 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5466
5467 do_process_instruction_dups(
5469 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5470 vec![mint_info.clone(), rent_info.clone()],
5471 )
5472 .unwrap();
5473
5474 let to_close_key = Pubkey::new_unique();
5475 let mut to_close_account = SolanaAccount::new(
5476 account_minimum_balance(),
5477 Account::get_packed_len(),
5478 &program_id,
5479 );
5480 let to_close_account_info: AccountInfo =
5481 (&to_close_key, true, &mut to_close_account).into();
5482 let destination_account_key = Pubkey::new_unique();
5483 let mut destination_account = SolanaAccount::new(
5484 account_minimum_balance(),
5485 Account::get_packed_len(),
5486 &program_id,
5487 );
5488 let destination_account_info: AccountInfo =
5489 (&destination_account_key, true, &mut destination_account).into();
5490 do_process_instruction_dups(
5492 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
5493 vec![
5494 to_close_account_info.clone(),
5495 mint_info.clone(),
5496 to_close_account_info.clone(),
5497 rent_info.clone(),
5498 ],
5499 )
5500 .unwrap();
5501
5502 do_process_instruction_dups(
5504 close_account(
5505 &program_id,
5506 &to_close_key,
5507 &destination_account_key,
5508 &to_close_key,
5509 &[],
5510 )
5511 .unwrap(),
5512 vec![
5513 to_close_account_info.clone(),
5514 destination_account_info.clone(),
5515 to_close_account_info.clone(),
5516 ],
5517 )
5518 .unwrap();
5519 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
5520 }
5521
5522 #[test]
5523 fn test_close_authority_close_account_dups() {
5524 let program_id = crate::id();
5525 let owner_key = Pubkey::new_unique();
5526 let mint_key = Pubkey::new_unique();
5527 let mut mint_account =
5528 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5529 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
5530 let rent_key = rent::id();
5531 let mut rent_sysvar = rent_sysvar();
5532 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5533
5534 do_process_instruction_dups(
5536 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5537 vec![mint_info.clone(), rent_info.clone()],
5538 )
5539 .unwrap();
5540
5541 let to_close_key = Pubkey::new_unique();
5542 let mut to_close_account = SolanaAccount::new(
5543 account_minimum_balance(),
5544 Account::get_packed_len(),
5545 &program_id,
5546 );
5547 let to_close_account_info: AccountInfo =
5548 (&to_close_key, true, &mut to_close_account).into();
5549 let destination_account_key = Pubkey::new_unique();
5550 let mut destination_account = SolanaAccount::new(
5551 account_minimum_balance(),
5552 Account::get_packed_len(),
5553 &program_id,
5554 );
5555 let destination_account_info: AccountInfo =
5556 (&destination_account_key, true, &mut destination_account).into();
5557 do_process_instruction_dups(
5559 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
5560 vec![
5561 to_close_account_info.clone(),
5562 mint_info.clone(),
5563 to_close_account_info.clone(),
5564 rent_info.clone(),
5565 ],
5566 )
5567 .unwrap();
5568 let mut account = Account::unpack_unchecked(&to_close_account_info.data.borrow()).unwrap();
5569 account.close_authority = COption::Some(to_close_key);
5570 account.owner = owner_key;
5571 Account::pack(account, &mut to_close_account_info.data.borrow_mut()).unwrap();
5572 do_process_instruction_dups(
5573 close_account(
5574 &program_id,
5575 &to_close_key,
5576 &destination_account_key,
5577 &to_close_key,
5578 &[],
5579 )
5580 .unwrap(),
5581 vec![
5582 to_close_account_info.clone(),
5583 destination_account_info.clone(),
5584 to_close_account_info.clone(),
5585 ],
5586 )
5587 .unwrap();
5588 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
5589 }
5590
5591 #[test]
5592 fn test_close_account() {
5593 let program_id = crate::id();
5594 let mint_key = Pubkey::new_unique();
5595 let mut mint_account =
5596 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5597 let account_key = Pubkey::new_unique();
5598 let mut account_account = SolanaAccount::new(
5599 account_minimum_balance(),
5600 Account::get_packed_len(),
5601 &program_id,
5602 );
5603 let account2_key = Pubkey::new_unique();
5604 let mut account2_account = SolanaAccount::new(
5605 account_minimum_balance() + 42,
5606 Account::get_packed_len(),
5607 &program_id,
5608 );
5609 let account3_key = Pubkey::new_unique();
5610 let mut account3_account = SolanaAccount::new(
5611 account_minimum_balance(),
5612 Account::get_packed_len(),
5613 &program_id,
5614 );
5615 let owner_key = Pubkey::new_unique();
5616 let mut owner_account = SolanaAccount::default();
5617 let owner2_key = Pubkey::new_unique();
5618 let mut owner2_account = SolanaAccount::default();
5619 let mut rent_sysvar = rent_sysvar();
5620
5621 assert_eq!(
5623 Err(ProgramError::UninitializedAccount),
5624 do_process_instruction(
5625 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5626 vec![
5627 &mut account_account,
5628 &mut account3_account,
5629 &mut owner2_account,
5630 ],
5631 )
5632 );
5633
5634 do_process_instruction(
5636 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5637 vec![&mut mint_account, &mut rent_sysvar],
5638 )
5639 .unwrap();
5640 do_process_instruction(
5641 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5642 vec![
5643 &mut account_account,
5644 &mut mint_account,
5645 &mut owner_account,
5646 &mut rent_sysvar,
5647 ],
5648 )
5649 .unwrap();
5650 do_process_instruction(
5651 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
5652 vec![
5653 &mut mint_account,
5654 &mut account_account,
5655 &mut owner_account,
5656 &mut rent_sysvar,
5657 ],
5658 )
5659 .unwrap();
5660 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5661 assert_eq!(account.amount, 42);
5662
5663 do_process_instruction(
5665 initialize_account(
5666 &program_id,
5667 &account2_key,
5668 &crate::native_mint::id(),
5669 &owner_key,
5670 )
5671 .unwrap(),
5672 vec![
5673 &mut account2_account,
5674 &mut mint_account,
5675 &mut owner_account,
5676 &mut rent_sysvar,
5677 ],
5678 )
5679 .unwrap();
5680 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5681 assert!(account.is_native());
5682 assert_eq!(account.amount, 42);
5683
5684 assert_eq!(
5686 Err(TokenError::NonNativeHasBalance.into()),
5687 do_process_instruction(
5688 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
5689 vec![
5690 &mut account_account,
5691 &mut account3_account,
5692 &mut owner_account,
5693 ],
5694 )
5695 );
5696 assert_eq!(account_account.lamports, account_minimum_balance());
5697
5698 do_process_instruction(
5700 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
5701 vec![&mut account_account, &mut mint_account, &mut owner_account],
5702 )
5703 .unwrap();
5704
5705 assert_eq!(
5707 Err(TokenError::OwnerMismatch.into()),
5708 do_process_instruction(
5709 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5710 vec![
5711 &mut account_account,
5712 &mut account3_account,
5713 &mut owner2_account,
5714 ],
5715 )
5716 );
5717
5718 do_process_instruction(
5720 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
5721 vec![
5722 &mut account_account,
5723 &mut account3_account,
5724 &mut owner_account,
5725 ],
5726 )
5727 .unwrap();
5728 assert_eq!(account_account.lamports, 0);
5729 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
5730 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5731 assert_eq!(account.amount, 0);
5732
5733 let account_key = Pubkey::new_unique();
5735 let mut account_account = SolanaAccount::new(
5736 account_minimum_balance(),
5737 Account::get_packed_len(),
5738 &program_id,
5739 );
5740 let owner2_key = Pubkey::new_unique();
5741 let mut owner2_account = SolanaAccount::new(
5742 account_minimum_balance(),
5743 Account::get_packed_len(),
5744 &program_id,
5745 );
5746 do_process_instruction(
5747 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5748 vec![
5749 &mut account_account,
5750 &mut mint_account,
5751 &mut owner_account,
5752 &mut rent_sysvar,
5753 ],
5754 )
5755 .unwrap();
5756 account_account.lamports = 2;
5757
5758 do_process_instruction(
5759 set_authority(
5760 &program_id,
5761 &account_key,
5762 Some(&owner2_key),
5763 AuthorityType::CloseAccount,
5764 &owner_key,
5765 &[],
5766 )
5767 .unwrap(),
5768 vec![&mut account_account, &mut owner_account],
5769 )
5770 .unwrap();
5771
5772 assert_eq!(
5774 Err(TokenError::OwnerMismatch.into()),
5775 do_process_instruction(
5776 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
5777 vec![
5778 &mut account_account,
5779 &mut account3_account,
5780 &mut owner_account,
5781 ],
5782 )
5783 );
5784
5785 do_process_instruction(
5787 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5788 vec![
5789 &mut account_account,
5790 &mut account3_account,
5791 &mut owner2_account,
5792 ],
5793 )
5794 .unwrap();
5795 assert_eq!(account_account.lamports, 0);
5796 assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2);
5797 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5798 assert_eq!(account.amount, 0);
5799
5800 do_process_instruction(
5802 close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
5803 vec![
5804 &mut account2_account,
5805 &mut account3_account,
5806 &mut owner_account,
5807 ],
5808 )
5809 .unwrap();
5810 assert_eq!(account2_account.data, [0u8; Account::LEN]);
5811 assert_eq!(
5812 account3_account.lamports,
5813 3 * account_minimum_balance() + 2 + 42
5814 );
5815 }
5816
5817 #[test]
5818 fn test_native_token() {
5819 let program_id = crate::id();
5820 let mut mint_account =
5821 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5822 let account_key = Pubkey::new_unique();
5823 let mut account_account = SolanaAccount::new(
5824 account_minimum_balance() + 40,
5825 Account::get_packed_len(),
5826 &program_id,
5827 );
5828 let account2_key = Pubkey::new_unique();
5829 let mut account2_account = SolanaAccount::new(
5830 account_minimum_balance(),
5831 Account::get_packed_len(),
5832 &program_id,
5833 );
5834 let account3_key = Pubkey::new_unique();
5835 let mut account3_account = SolanaAccount::new(account_minimum_balance(), 0, &program_id);
5836 let owner_key = Pubkey::new_unique();
5837 let mut owner_account = SolanaAccount::default();
5838 let owner2_key = Pubkey::new_unique();
5839 let mut owner2_account = SolanaAccount::default();
5840 let owner3_key = Pubkey::new_unique();
5841 let mut rent_sysvar = rent_sysvar();
5842
5843 do_process_instruction(
5845 initialize_account(
5846 &program_id,
5847 &account_key,
5848 &crate::native_mint::id(),
5849 &owner_key,
5850 )
5851 .unwrap(),
5852 vec![
5853 &mut account_account,
5854 &mut mint_account,
5855 &mut owner_account,
5856 &mut rent_sysvar,
5857 ],
5858 )
5859 .unwrap();
5860 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5861 assert!(account.is_native());
5862 assert_eq!(account.amount, 40);
5863
5864 do_process_instruction(
5866 initialize_account(
5867 &program_id,
5868 &account2_key,
5869 &crate::native_mint::id(),
5870 &owner_key,
5871 )
5872 .unwrap(),
5873 vec![
5874 &mut account2_account,
5875 &mut mint_account,
5876 &mut owner_account,
5877 &mut rent_sysvar,
5878 ],
5879 )
5880 .unwrap();
5881 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5882 assert!(account.is_native());
5883 assert_eq!(account.amount, 0);
5884
5885 assert_eq!(
5887 Err(TokenError::NativeNotSupported.into()),
5888 do_process_instruction(
5889 mint_to(
5890 &program_id,
5891 &crate::native_mint::id(),
5892 &account_key,
5893 &owner_key,
5894 &[],
5895 42
5896 )
5897 .unwrap(),
5898 vec![&mut mint_account, &mut account_account, &mut owner_account],
5899 )
5900 );
5901
5902 let bogus_mint_key = Pubkey::new_unique();
5904 let mut bogus_mint_account =
5905 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5906 do_process_instruction(
5907 initialize_mint(&program_id, &bogus_mint_key, &owner_key, None, 2).unwrap(),
5908 vec![&mut bogus_mint_account, &mut rent_sysvar],
5909 )
5910 .unwrap();
5911
5912 assert_eq!(
5913 Err(TokenError::NativeNotSupported.into()),
5914 do_process_instruction(
5915 burn(
5916 &program_id,
5917 &account_key,
5918 &bogus_mint_key,
5919 &owner_key,
5920 &[],
5921 42
5922 )
5923 .unwrap(),
5924 vec![
5925 &mut account_account,
5926 &mut bogus_mint_account,
5927 &mut owner_account
5928 ],
5929 )
5930 );
5931
5932 assert_eq!(
5934 Err(TokenError::InsufficientFunds.into()),
5935 do_process_instruction(
5936 transfer(
5937 &program_id,
5938 &account_key,
5939 &account2_key,
5940 &owner_key,
5941 &[],
5942 50,
5943 )
5944 .unwrap(),
5945 vec![
5946 &mut account_account,
5947 &mut account2_account,
5948 &mut owner_account,
5949 ],
5950 )
5951 );
5952
5953 do_process_instruction(
5955 transfer(
5956 &program_id,
5957 &account_key,
5958 &account2_key,
5959 &owner_key,
5960 &[],
5961 40,
5962 )
5963 .unwrap(),
5964 vec![
5965 &mut account_account,
5966 &mut account2_account,
5967 &mut owner_account,
5968 ],
5969 )
5970 .unwrap();
5971 assert_eq!(account_account.lamports, account_minimum_balance());
5972 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5973 assert!(account.is_native());
5974 assert_eq!(account.amount, 0);
5975 assert_eq!(account2_account.lamports, account_minimum_balance() + 40);
5976 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5977 assert!(account.is_native());
5978 assert_eq!(account.amount, 40);
5979
5980 do_process_instruction(
5982 set_authority(
5983 &program_id,
5984 &account_key,
5985 Some(&owner3_key),
5986 AuthorityType::CloseAccount,
5987 &owner_key,
5988 &[],
5989 )
5990 .unwrap(),
5991 vec![&mut account_account, &mut owner_account],
5992 )
5993 .unwrap();
5994 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5995 assert_eq!(account.close_authority, COption::Some(owner3_key));
5996
5997 do_process_instruction(
5999 set_authority(
6000 &program_id,
6001 &account_key,
6002 Some(&owner2_key),
6003 AuthorityType::AccountOwner,
6004 &owner_key,
6005 &[],
6006 )
6007 .unwrap(),
6008 vec![&mut account_account, &mut owner_account],
6009 )
6010 .unwrap();
6011
6012 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6014 assert_eq!(account.close_authority, COption::None);
6015
6016 do_process_instruction(
6018 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
6019 vec![
6020 &mut account_account,
6021 &mut account3_account,
6022 &mut owner2_account,
6023 ],
6024 )
6025 .unwrap();
6026 assert_eq!(account_account.lamports, 0);
6027 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
6028 assert_eq!(account_account.data, [0u8; Account::LEN]);
6029 }
6030
6031 #[test]
6032 fn test_overflow() {
6033 let program_id = crate::id();
6034 let account_key = Pubkey::new_unique();
6035 let mut account_account = SolanaAccount::new(
6036 account_minimum_balance(),
6037 Account::get_packed_len(),
6038 &program_id,
6039 );
6040 let account2_key = Pubkey::new_unique();
6041 let mut account2_account = SolanaAccount::new(
6042 account_minimum_balance(),
6043 Account::get_packed_len(),
6044 &program_id,
6045 );
6046 let owner_key = Pubkey::new_unique();
6047 let mut owner_account = SolanaAccount::default();
6048 let owner2_key = Pubkey::new_unique();
6049 let mut owner2_account = SolanaAccount::default();
6050 let mint_owner_key = Pubkey::new_unique();
6051 let mut mint_owner_account = SolanaAccount::default();
6052 let mint_key = Pubkey::new_unique();
6053 let mut mint_account =
6054 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6055 let mut rent_sysvar = rent_sysvar();
6056
6057 do_process_instruction(
6059 initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
6060 vec![&mut mint_account, &mut rent_sysvar],
6061 )
6062 .unwrap();
6063
6064 do_process_instruction(
6066 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6067 vec![
6068 &mut account_account,
6069 &mut mint_account,
6070 &mut owner_account,
6071 &mut rent_sysvar,
6072 ],
6073 )
6074 .unwrap();
6075
6076 do_process_instruction(
6078 initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
6079 vec![
6080 &mut account2_account,
6081 &mut mint_account,
6082 &mut owner2_account,
6083 &mut rent_sysvar,
6084 ],
6085 )
6086 .unwrap();
6087
6088 do_process_instruction(
6090 mint_to(
6091 &program_id,
6092 &mint_key,
6093 &account_key,
6094 &mint_owner_key,
6095 &[],
6096 u64::MAX,
6097 )
6098 .unwrap(),
6099 vec![
6100 &mut mint_account,
6101 &mut account_account,
6102 &mut mint_owner_account,
6103 ],
6104 )
6105 .unwrap();
6106 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6107 assert_eq!(account.amount, u64::MAX);
6108
6109 assert_eq!(
6111 Err(TokenError::Overflow.into()),
6112 do_process_instruction(
6113 mint_to(
6114 &program_id,
6115 &mint_key,
6116 &account_key,
6117 &mint_owner_key,
6118 &[],
6119 1,
6120 )
6121 .unwrap(),
6122 vec![
6123 &mut mint_account,
6124 &mut account_account,
6125 &mut mint_owner_account,
6126 ],
6127 )
6128 );
6129 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6130 assert_eq!(account.amount, u64::MAX);
6131
6132 assert_eq!(
6134 Err(TokenError::Overflow.into()),
6135 do_process_instruction(
6136 mint_to(
6137 &program_id,
6138 &mint_key,
6139 &account2_key,
6140 &mint_owner_key,
6141 &[],
6142 1,
6143 )
6144 .unwrap(),
6145 vec![
6146 &mut mint_account,
6147 &mut account2_account,
6148 &mut mint_owner_account,
6149 ],
6150 )
6151 );
6152
6153 do_process_instruction(
6155 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
6156 vec![&mut account_account, &mut mint_account, &mut owner_account],
6157 )
6158 .unwrap();
6159 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6160 assert_eq!(account.amount, u64::MAX - 100);
6161
6162 do_process_instruction(
6163 mint_to(
6164 &program_id,
6165 &mint_key,
6166 &account_key,
6167 &mint_owner_key,
6168 &[],
6169 100,
6170 )
6171 .unwrap(),
6172 vec![
6173 &mut mint_account,
6174 &mut account_account,
6175 &mut mint_owner_account,
6176 ],
6177 )
6178 .unwrap();
6179 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6180 assert_eq!(account.amount, u64::MAX);
6181
6182 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
6184 account.amount = 1;
6185 Account::pack(account, &mut account2_account.data).unwrap();
6186
6187 assert_eq!(
6188 Err(TokenError::Overflow.into()),
6189 do_process_instruction(
6190 transfer(
6191 &program_id,
6192 &account2_key,
6193 &account_key,
6194 &owner2_key,
6195 &[],
6196 1,
6197 )
6198 .unwrap(),
6199 vec![
6200 &mut account2_account,
6201 &mut account_account,
6202 &mut owner2_account,
6203 ],
6204 )
6205 );
6206 }
6207
6208 #[test]
6209 fn test_frozen() {
6210 let program_id = crate::id();
6211 let account_key = Pubkey::new_unique();
6212 let mut account_account = SolanaAccount::new(
6213 account_minimum_balance(),
6214 Account::get_packed_len(),
6215 &program_id,
6216 );
6217 let account2_key = Pubkey::new_unique();
6218 let mut account2_account = SolanaAccount::new(
6219 account_minimum_balance(),
6220 Account::get_packed_len(),
6221 &program_id,
6222 );
6223 let owner_key = Pubkey::new_unique();
6224 let mut owner_account = SolanaAccount::default();
6225 let mint_key = Pubkey::new_unique();
6226 let mut mint_account =
6227 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6228 let mut rent_sysvar = rent_sysvar();
6229
6230 do_process_instruction(
6232 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6233 vec![&mut mint_account, &mut rent_sysvar],
6234 )
6235 .unwrap();
6236
6237 do_process_instruction(
6239 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6240 vec![
6241 &mut account_account,
6242 &mut mint_account,
6243 &mut owner_account,
6244 &mut rent_sysvar,
6245 ],
6246 )
6247 .unwrap();
6248
6249 do_process_instruction(
6251 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
6252 vec![
6253 &mut account2_account,
6254 &mut mint_account,
6255 &mut owner_account,
6256 &mut rent_sysvar,
6257 ],
6258 )
6259 .unwrap();
6260
6261 do_process_instruction(
6263 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
6264 vec![&mut mint_account, &mut account_account, &mut owner_account],
6265 )
6266 .unwrap();
6267
6268 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
6270 account.state = AccountState::Frozen;
6271 Account::pack(account, &mut account2_account.data).unwrap();
6272 assert_eq!(
6273 Err(TokenError::AccountFrozen.into()),
6274 do_process_instruction(
6275 transfer(
6276 &program_id,
6277 &account_key,
6278 &account2_key,
6279 &owner_key,
6280 &[],
6281 500,
6282 )
6283 .unwrap(),
6284 vec![
6285 &mut account_account,
6286 &mut account2_account,
6287 &mut owner_account,
6288 ],
6289 )
6290 );
6291
6292 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
6293 account.state = AccountState::Initialized;
6294 Account::pack(account, &mut account_account.data).unwrap();
6295 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
6296 account.state = AccountState::Frozen;
6297 Account::pack(account, &mut account2_account.data).unwrap();
6298 assert_eq!(
6299 Err(TokenError::AccountFrozen.into()),
6300 do_process_instruction(
6301 transfer(
6302 &program_id,
6303 &account_key,
6304 &account2_key,
6305 &owner_key,
6306 &[],
6307 500,
6308 )
6309 .unwrap(),
6310 vec![
6311 &mut account_account,
6312 &mut account2_account,
6313 &mut owner_account,
6314 ],
6315 )
6316 );
6317
6318 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
6320 account.state = AccountState::Frozen;
6321 Account::pack(account, &mut account_account.data).unwrap();
6322 let delegate_key = Pubkey::new_unique();
6323 let mut delegate_account = SolanaAccount::default();
6324 assert_eq!(
6325 Err(TokenError::AccountFrozen.into()),
6326 do_process_instruction(
6327 approve(
6328 &program_id,
6329 &account_key,
6330 &delegate_key,
6331 &owner_key,
6332 &[],
6333 100
6334 )
6335 .unwrap(),
6336 vec![
6337 &mut account_account,
6338 &mut delegate_account,
6339 &mut owner_account,
6340 ],
6341 )
6342 );
6343
6344 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
6346 account.delegate = COption::Some(delegate_key);
6347 account.delegated_amount = 100;
6348 Account::pack(account, &mut account_account.data).unwrap();
6349 assert_eq!(
6350 Err(TokenError::AccountFrozen.into()),
6351 do_process_instruction(
6352 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
6353 vec![&mut account_account, &mut owner_account],
6354 )
6355 );
6356
6357 let new_owner_key = Pubkey::new_unique();
6359 assert_eq!(
6360 Err(TokenError::AccountFrozen.into()),
6361 do_process_instruction(
6362 set_authority(
6363 &program_id,
6364 &account_key,
6365 Some(&new_owner_key),
6366 AuthorityType::AccountOwner,
6367 &owner_key,
6368 &[]
6369 )
6370 .unwrap(),
6371 vec![&mut account_account, &mut owner_account,],
6372 )
6373 );
6374
6375 assert_eq!(
6377 Err(TokenError::AccountFrozen.into()),
6378 do_process_instruction(
6379 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 100).unwrap(),
6380 vec![&mut mint_account, &mut account_account, &mut owner_account,],
6381 )
6382 );
6383
6384 assert_eq!(
6386 Err(TokenError::AccountFrozen.into()),
6387 do_process_instruction(
6388 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
6389 vec![&mut account_account, &mut mint_account, &mut owner_account],
6390 )
6391 );
6392 }
6393
6394 #[test]
6395 fn test_freeze_thaw_dups() {
6396 let program_id = crate::id();
6397 let account1_key = Pubkey::new_unique();
6398 let mut account1_account = SolanaAccount::new(
6399 account_minimum_balance(),
6400 Account::get_packed_len(),
6401 &program_id,
6402 );
6403 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
6404 let owner_key = Pubkey::new_unique();
6405 let mint_key = Pubkey::new_unique();
6406 let mut mint_account =
6407 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6408 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
6409 let rent_key = rent::id();
6410 let mut rent_sysvar = rent_sysvar();
6411 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6412
6413 do_process_instruction_dups(
6415 initialize_mint(&program_id, &mint_key, &owner_key, Some(&account1_key), 2).unwrap(),
6416 vec![mint_info.clone(), rent_info.clone()],
6417 )
6418 .unwrap();
6419
6420 do_process_instruction_dups(
6422 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
6423 vec![
6424 account1_info.clone(),
6425 mint_info.clone(),
6426 account1_info.clone(),
6427 rent_info.clone(),
6428 ],
6429 )
6430 .unwrap();
6431
6432 do_process_instruction_dups(
6434 freeze_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
6435 vec![
6436 account1_info.clone(),
6437 mint_info.clone(),
6438 account1_info.clone(),
6439 ],
6440 )
6441 .unwrap();
6442
6443 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
6445 account.state = AccountState::Frozen;
6446 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
6447 do_process_instruction_dups(
6448 thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
6449 vec![
6450 account1_info.clone(),
6451 mint_info.clone(),
6452 account1_info.clone(),
6453 ],
6454 )
6455 .unwrap();
6456 }
6457
6458 #[test]
6459 fn test_freeze_account() {
6460 let program_id = crate::id();
6461 let account_key = Pubkey::new_unique();
6462 let mut account_account = SolanaAccount::new(
6463 account_minimum_balance(),
6464 Account::get_packed_len(),
6465 &program_id,
6466 );
6467 let account_owner_key = Pubkey::new_unique();
6468 let mut account_owner_account = SolanaAccount::default();
6469 let owner_key = Pubkey::new_unique();
6470 let mut owner_account = SolanaAccount::default();
6471 let owner2_key = Pubkey::new_unique();
6472 let mut owner2_account = SolanaAccount::default();
6473 let mint_key = Pubkey::new_unique();
6474 let mut mint_account =
6475 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6476 let mut rent_sysvar = rent_sysvar();
6477
6478 do_process_instruction(
6480 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6481 vec![&mut mint_account, &mut rent_sysvar],
6482 )
6483 .unwrap();
6484
6485 do_process_instruction(
6487 initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
6488 vec![
6489 &mut account_account,
6490 &mut mint_account,
6491 &mut account_owner_account,
6492 &mut rent_sysvar,
6493 ],
6494 )
6495 .unwrap();
6496
6497 do_process_instruction(
6499 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
6500 vec![&mut mint_account, &mut account_account, &mut owner_account],
6501 )
6502 .unwrap();
6503
6504 assert_eq!(
6506 Err(TokenError::MintCannotFreeze.into()),
6507 do_process_instruction(
6508 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6509 vec![&mut account_account, &mut mint_account, &mut owner_account],
6510 )
6511 );
6512
6513 let mut mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
6515 mint.freeze_authority = COption::Some(owner_key);
6516 Mint::pack(mint, &mut mint_account.data).unwrap();
6517 assert_eq!(
6518 Err(TokenError::OwnerMismatch.into()),
6519 do_process_instruction(
6520 freeze_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
6521 vec![&mut account_account, &mut mint_account, &mut owner2_account],
6522 )
6523 );
6524
6525 assert_eq!(
6527 Err(TokenError::InvalidState.into()),
6528 do_process_instruction(
6529 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
6530 vec![&mut account_account, &mut mint_account, &mut owner2_account],
6531 )
6532 );
6533
6534 do_process_instruction(
6536 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6537 vec![&mut account_account, &mut mint_account, &mut owner_account],
6538 )
6539 .unwrap();
6540 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6541 assert_eq!(account.state, AccountState::Frozen);
6542
6543 assert_eq!(
6545 Err(TokenError::InvalidState.into()),
6546 do_process_instruction(
6547 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6548 vec![&mut account_account, &mut mint_account, &mut owner_account],
6549 )
6550 );
6551
6552 assert_eq!(
6554 Err(TokenError::OwnerMismatch.into()),
6555 do_process_instruction(
6556 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
6557 vec![&mut account_account, &mut mint_account, &mut owner2_account],
6558 )
6559 );
6560
6561 do_process_instruction(
6563 thaw_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6564 vec![&mut account_account, &mut mint_account, &mut owner_account],
6565 )
6566 .unwrap();
6567 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6568 assert_eq!(account.state, AccountState::Initialized);
6569 }
6570
6571 #[test]
6572 fn test_initialize_account2_and_3() {
6573 let program_id = crate::id();
6574 let account_key = Pubkey::new_unique();
6575 let mut account_account = SolanaAccount::new(
6576 account_minimum_balance(),
6577 Account::get_packed_len(),
6578 &program_id,
6579 );
6580 let mut account2_account = SolanaAccount::new(
6581 account_minimum_balance(),
6582 Account::get_packed_len(),
6583 &program_id,
6584 );
6585 let mut account3_account = SolanaAccount::new(
6586 account_minimum_balance(),
6587 Account::get_packed_len(),
6588 &program_id,
6589 );
6590 let owner_key = Pubkey::new_unique();
6591 let mut owner_account = SolanaAccount::default();
6592 let mint_key = Pubkey::new_unique();
6593 let mut mint_account =
6594 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6595 let mut rent_sysvar = rent_sysvar();
6596
6597 do_process_instruction(
6599 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6600 vec![&mut mint_account, &mut rent_sysvar],
6601 )
6602 .unwrap();
6603
6604 do_process_instruction(
6605 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6606 vec![
6607 &mut account_account,
6608 &mut mint_account,
6609 &mut owner_account,
6610 &mut rent_sysvar,
6611 ],
6612 )
6613 .unwrap();
6614
6615 do_process_instruction(
6616 initialize_account2(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6617 vec![&mut account2_account, &mut mint_account, &mut rent_sysvar],
6618 )
6619 .unwrap();
6620
6621 assert_eq!(account_account, account2_account);
6622
6623 do_process_instruction(
6624 initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6625 vec![&mut account3_account, &mut mint_account],
6626 )
6627 .unwrap();
6628
6629 assert_eq!(account_account, account3_account);
6630 }
6631
6632 #[test]
6633 fn test_sync_native() {
6634 let program_id = crate::id();
6635 let mint_key = Pubkey::new_unique();
6636 let mut mint_account =
6637 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6638 let native_account_key = Pubkey::new_unique();
6639 let lamports = 40;
6640 let mut native_account = SolanaAccount::new(
6641 account_minimum_balance() + lamports,
6642 Account::get_packed_len(),
6643 &program_id,
6644 );
6645 let non_native_account_key = Pubkey::new_unique();
6646 let mut non_native_account = SolanaAccount::new(
6647 account_minimum_balance() + 50,
6648 Account::get_packed_len(),
6649 &program_id,
6650 );
6651
6652 let owner_key = Pubkey::new_unique();
6653 let mut owner_account = SolanaAccount::default();
6654 let mut rent_sysvar = rent_sysvar();
6655
6656 do_process_instruction(
6658 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6659 vec![&mut mint_account, &mut rent_sysvar],
6660 )
6661 .unwrap();
6662
6663 do_process_instruction(
6665 initialize_account(&program_id, &non_native_account_key, &mint_key, &owner_key)
6666 .unwrap(),
6667 vec![
6668 &mut non_native_account,
6669 &mut mint_account,
6670 &mut owner_account,
6671 &mut rent_sysvar,
6672 ],
6673 )
6674 .unwrap();
6675
6676 let account = Account::unpack_unchecked(&non_native_account.data).unwrap();
6677 assert!(!account.is_native());
6678 assert_eq!(account.amount, 0);
6679
6680 assert_eq!(
6682 Err(TokenError::NonNativeNotSupported.into()),
6683 do_process_instruction(
6684 sync_native(&program_id, &non_native_account_key,).unwrap(),
6685 vec![&mut non_native_account],
6686 )
6687 );
6688
6689 assert_eq!(
6691 Err(ProgramError::UninitializedAccount),
6692 do_process_instruction(
6693 sync_native(&program_id, &native_account_key,).unwrap(),
6694 vec![&mut native_account],
6695 )
6696 );
6697
6698 do_process_instruction(
6700 initialize_account(
6701 &program_id,
6702 &native_account_key,
6703 &crate::native_mint::id(),
6704 &owner_key,
6705 )
6706 .unwrap(),
6707 vec![
6708 &mut native_account,
6709 &mut mint_account,
6710 &mut owner_account,
6711 &mut rent_sysvar,
6712 ],
6713 )
6714 .unwrap();
6715
6716 let not_program_id = Pubkey::new_unique();
6718 native_account.owner = not_program_id;
6719 assert_eq!(
6720 Err(ProgramError::IncorrectProgramId),
6721 do_process_instruction(
6722 sync_native(&program_id, &native_account_key,).unwrap(),
6723 vec![&mut native_account],
6724 )
6725 );
6726 native_account.owner = program_id;
6727
6728 let account = Account::unpack_unchecked(&native_account.data).unwrap();
6729 assert!(account.is_native());
6730 assert_eq!(account.amount, lamports);
6731
6732 do_process_instruction(
6734 sync_native(&program_id, &native_account_key).unwrap(),
6735 vec![&mut native_account],
6736 )
6737 .unwrap();
6738 let account = Account::unpack_unchecked(&native_account.data).unwrap();
6739 assert_eq!(account.amount, lamports);
6740
6741 let new_lamports = lamports + 50;
6743 native_account.lamports = account_minimum_balance() + new_lamports;
6744
6745 do_process_instruction(
6747 sync_native(&program_id, &native_account_key).unwrap(),
6748 vec![&mut native_account],
6749 )
6750 .unwrap();
6751 let account = Account::unpack_unchecked(&native_account.data).unwrap();
6752 assert_eq!(account.amount, new_lamports);
6753
6754 native_account.lamports -= 1;
6756
6757 assert_eq!(
6759 Err(TokenError::InvalidState.into()),
6760 do_process_instruction(
6761 sync_native(&program_id, &native_account_key,).unwrap(),
6762 vec![&mut native_account],
6763 )
6764 );
6765 }
6766
6767 #[test]
6768 #[serial]
6769 fn test_get_account_data_size() {
6770 let program_id = crate::id();
6772 let owner_key = Pubkey::new_unique();
6773 let mut rent_sysvar = rent_sysvar();
6774 let mut mint_account =
6775 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6776 let mint_key = Pubkey::new_unique();
6777 assert_eq!(
6779 Err(TokenError::InvalidMint.into()),
6780 do_process_instruction(
6781 get_account_data_size(&program_id, &mint_key).unwrap(),
6782 vec![&mut mint_account],
6783 )
6784 );
6785
6786 do_process_instruction(
6787 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6788 vec![&mut mint_account, &mut rent_sysvar],
6789 )
6790 .unwrap();
6791
6792 set_expected_data(Account::LEN.to_le_bytes().to_vec());
6793 do_process_instruction(
6794 get_account_data_size(&program_id, &mint_key).unwrap(),
6795 vec![&mut mint_account],
6796 )
6797 .unwrap();
6798 }
6799
6800 #[test]
6801 fn test_initialize_immutable_owner() {
6802 let program_id = crate::id();
6803 let account_key = Pubkey::new_unique();
6804 let mut account_account = SolanaAccount::new(
6805 account_minimum_balance(),
6806 Account::get_packed_len(),
6807 &program_id,
6808 );
6809 let owner_key = Pubkey::new_unique();
6810 let mut owner_account = SolanaAccount::default();
6811 let mint_key = Pubkey::new_unique();
6812 let mut mint_account =
6813 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6814 let mut rent_sysvar = rent_sysvar();
6815
6816 do_process_instruction(
6818 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6819 vec![&mut mint_account, &mut rent_sysvar],
6820 )
6821 .unwrap();
6822
6823 do_process_instruction(
6825 initialize_immutable_owner(&program_id, &account_key).unwrap(),
6826 vec![&mut account_account],
6827 )
6828 .unwrap();
6829
6830 do_process_instruction(
6832 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6833 vec![
6834 &mut account_account,
6835 &mut mint_account,
6836 &mut owner_account,
6837 &mut rent_sysvar,
6838 ],
6839 )
6840 .unwrap();
6841
6842 assert_eq!(
6844 Err(TokenError::AlreadyInUse.into()),
6845 do_process_instruction(
6846 initialize_immutable_owner(&program_id, &account_key).unwrap(),
6847 vec![&mut account_account],
6848 )
6849 );
6850 }
6851
6852 #[test]
6853 #[serial]
6854 fn test_amount_to_ui_amount() {
6855 let program_id = crate::id();
6856 let owner_key = Pubkey::new_unique();
6857 let mint_key = Pubkey::new_unique();
6858 let mut mint_account =
6859 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6860 let mut rent_sysvar = rent_sysvar();
6861
6862 assert_eq!(
6864 Err(TokenError::InvalidMint.into()),
6865 do_process_instruction(
6866 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
6867 vec![&mut mint_account],
6868 )
6869 );
6870
6871 do_process_instruction(
6873 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6874 vec![&mut mint_account, &mut rent_sysvar],
6875 )
6876 .unwrap();
6877
6878 set_expected_data("0.23".as_bytes().to_vec());
6879 do_process_instruction(
6880 amount_to_ui_amount(&program_id, &mint_key, 23).unwrap(),
6881 vec![&mut mint_account],
6882 )
6883 .unwrap();
6884
6885 set_expected_data("1.1".as_bytes().to_vec());
6886 do_process_instruction(
6887 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
6888 vec![&mut mint_account],
6889 )
6890 .unwrap();
6891
6892 set_expected_data("42".as_bytes().to_vec());
6893 do_process_instruction(
6894 amount_to_ui_amount(&program_id, &mint_key, 4200).unwrap(),
6895 vec![&mut mint_account],
6896 )
6897 .unwrap();
6898
6899 set_expected_data("0".as_bytes().to_vec());
6900 do_process_instruction(
6901 amount_to_ui_amount(&program_id, &mint_key, 0).unwrap(),
6902 vec![&mut mint_account],
6903 )
6904 .unwrap();
6905 }
6906
6907 #[test]
6908 #[serial]
6909 fn test_ui_amount_to_amount() {
6910 let program_id = crate::id();
6911 let owner_key = Pubkey::new_unique();
6912 let mint_key = Pubkey::new_unique();
6913 let mut mint_account =
6914 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6915 let mut rent_sysvar = rent_sysvar();
6916
6917 assert_eq!(
6919 Err(TokenError::InvalidMint.into()),
6920 do_process_instruction(
6921 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
6922 vec![&mut mint_account],
6923 )
6924 );
6925
6926 do_process_instruction(
6928 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6929 vec![&mut mint_account, &mut rent_sysvar],
6930 )
6931 .unwrap();
6932
6933 set_expected_data(23u64.to_le_bytes().to_vec());
6934 do_process_instruction(
6935 ui_amount_to_amount(&program_id, &mint_key, "0.23").unwrap(),
6936 vec![&mut mint_account],
6937 )
6938 .unwrap();
6939
6940 set_expected_data(20u64.to_le_bytes().to_vec());
6941 do_process_instruction(
6942 ui_amount_to_amount(&program_id, &mint_key, "0.20").unwrap(),
6943 vec![&mut mint_account],
6944 )
6945 .unwrap();
6946
6947 set_expected_data(20u64.to_le_bytes().to_vec());
6948 do_process_instruction(
6949 ui_amount_to_amount(&program_id, &mint_key, "0.2000").unwrap(),
6950 vec![&mut mint_account],
6951 )
6952 .unwrap();
6953
6954 set_expected_data(20u64.to_le_bytes().to_vec());
6955 do_process_instruction(
6956 ui_amount_to_amount(&program_id, &mint_key, ".20").unwrap(),
6957 vec![&mut mint_account],
6958 )
6959 .unwrap();
6960
6961 set_expected_data(110u64.to_le_bytes().to_vec());
6962 do_process_instruction(
6963 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
6964 vec![&mut mint_account],
6965 )
6966 .unwrap();
6967
6968 set_expected_data(110u64.to_le_bytes().to_vec());
6969 do_process_instruction(
6970 ui_amount_to_amount(&program_id, &mint_key, "1.10").unwrap(),
6971 vec![&mut mint_account],
6972 )
6973 .unwrap();
6974
6975 set_expected_data(4200u64.to_le_bytes().to_vec());
6976 do_process_instruction(
6977 ui_amount_to_amount(&program_id, &mint_key, "42").unwrap(),
6978 vec![&mut mint_account],
6979 )
6980 .unwrap();
6981
6982 set_expected_data(4200u64.to_le_bytes().to_vec());
6983 do_process_instruction(
6984 ui_amount_to_amount(&program_id, &mint_key, "42.").unwrap(),
6985 vec![&mut mint_account],
6986 )
6987 .unwrap();
6988
6989 set_expected_data(0u64.to_le_bytes().to_vec());
6990 do_process_instruction(
6991 ui_amount_to_amount(&program_id, &mint_key, "0").unwrap(),
6992 vec![&mut mint_account],
6993 )
6994 .unwrap();
6995
6996 assert_eq!(
6998 Err(ProgramError::InvalidArgument),
6999 do_process_instruction(
7000 ui_amount_to_amount(&program_id, &mint_key, "").unwrap(),
7001 vec![&mut mint_account],
7002 )
7003 );
7004 assert_eq!(
7005 Err(ProgramError::InvalidArgument),
7006 do_process_instruction(
7007 ui_amount_to_amount(&program_id, &mint_key, ".").unwrap(),
7008 vec![&mut mint_account],
7009 )
7010 );
7011 assert_eq!(
7012 Err(ProgramError::InvalidArgument),
7013 do_process_instruction(
7014 ui_amount_to_amount(&program_id, &mint_key, "0.111").unwrap(),
7015 vec![&mut mint_account],
7016 )
7017 );
7018 assert_eq!(
7019 Err(ProgramError::InvalidArgument),
7020 do_process_instruction(
7021 ui_amount_to_amount(&program_id, &mint_key, "0.t").unwrap(),
7022 vec![&mut mint_account],
7023 )
7024 );
7025 }
7026}