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