extended_mint.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. use {
  2. mollusk_svm::result::Check,
  3. solana_program_error::ProgramError,
  4. spl_associated_token_account_mollusk_harness::AtaTestHarness,
  5. spl_token_2022_interface::{
  6. extension::{
  7. transfer_fee, BaseStateWithExtensions, ExtensionType, StateWithExtensionsOwned,
  8. },
  9. state::Account,
  10. },
  11. };
  12. #[test]
  13. fn test_associated_token_account_with_transfer_fees() {
  14. let maximum_fee = 100;
  15. let transfer_fee_basis_points = 1_000;
  16. let (harness, receiver_wallet) = AtaTestHarness::new(&spl_token_2022_interface::id())
  17. .with_wallet(1_000_000)
  18. .with_additional_wallet(1_000_000);
  19. let mut harness = harness
  20. .with_mint_with_extensions(&[ExtensionType::TransferFeeConfig])
  21. .initialize_transfer_fee(transfer_fee_basis_points, maximum_fee)
  22. .initialize_mint(0)
  23. .with_ata();
  24. let (sender_pubkey, mint, sender_ata, receiver_ata) = (
  25. harness.wallet.unwrap(),
  26. harness.mint.unwrap(),
  27. harness.ata_address.unwrap(),
  28. harness.create_ata_for_owner(receiver_wallet, 1_000_000),
  29. );
  30. harness.mint_tokens(50 * maximum_fee);
  31. // Insufficient funds transfer
  32. harness.ctx.process_and_validate_instruction(
  33. &transfer_fee::instruction::transfer_checked_with_fee(
  34. &spl_token_2022_interface::id(),
  35. &sender_ata,
  36. &mint,
  37. &receiver_ata,
  38. &sender_pubkey,
  39. &[],
  40. 10_001,
  41. 0,
  42. maximum_fee,
  43. )
  44. .unwrap(),
  45. &[Check::err(ProgramError::Custom(
  46. spl_token_2022_interface::error::TokenError::InsufficientFunds as u32,
  47. ))],
  48. );
  49. // Successful transfer
  50. let (transfer_amount, fee) = (500, 50);
  51. harness.ctx.process_and_validate_instruction(
  52. &transfer_fee::instruction::transfer_checked_with_fee(
  53. &spl_token_2022_interface::id(),
  54. &sender_ata,
  55. &mint,
  56. &receiver_ata,
  57. &sender_pubkey,
  58. &[],
  59. transfer_amount,
  60. 0,
  61. fee,
  62. )
  63. .unwrap(),
  64. &[Check::success()],
  65. );
  66. // Verify final account states
  67. let sender_state =
  68. StateWithExtensionsOwned::<Account>::unpack(harness.get_account(sender_ata).data).unwrap();
  69. assert_eq!(sender_state.base.amount, 50 * maximum_fee - transfer_amount);
  70. assert_eq!(
  71. sender_state
  72. .get_extension::<transfer_fee::TransferFeeAmount>()
  73. .unwrap()
  74. .withheld_amount,
  75. 0.into()
  76. );
  77. let receiver_state =
  78. StateWithExtensionsOwned::<Account>::unpack(harness.get_account(receiver_ata).data)
  79. .unwrap();
  80. assert_eq!(receiver_state.base.amount, transfer_amount - fee);
  81. assert_eq!(
  82. receiver_state
  83. .get_extension::<transfer_fee::TransferFeeAmount>()
  84. .unwrap()
  85. .withheld_amount,
  86. fee.into()
  87. );
  88. }