lib.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. use {
  2. borsh::{BorshDeserialize, BorshSerialize},
  3. solana_program::{
  4. account_info::{next_account_info, AccountInfo},
  5. entrypoint,
  6. entrypoint::ProgramResult,
  7. msg,
  8. program::invoke,
  9. pubkey::Pubkey,
  10. rent::Rent,
  11. system_instruction,
  12. sysvar::Sysvar,
  13. },
  14. spl_token_2022::{
  15. extension::{
  16. transfer_fee::instruction::{initialize_transfer_fee_config, set_transfer_fee},
  17. ExtensionType,
  18. },
  19. instruction as token_instruction,
  20. state::Mint,
  21. },
  22. };
  23. #[derive(BorshSerialize, BorshDeserialize, Debug)]
  24. pub struct CreateTokenArgs {
  25. pub token_decimals: u8,
  26. }
  27. entrypoint!(process_instruction);
  28. fn process_instruction(
  29. _program_id: &Pubkey,
  30. accounts: &[AccountInfo],
  31. instruction_data: &[u8],
  32. ) -> ProgramResult {
  33. let args = CreateTokenArgs::try_from_slice(instruction_data)?;
  34. let accounts_iter = &mut accounts.iter();
  35. let mint_account = next_account_info(accounts_iter)?;
  36. let mint_authority = next_account_info(accounts_iter)?;
  37. let payer = next_account_info(accounts_iter)?;
  38. let rent = next_account_info(accounts_iter)?;
  39. let system_program = next_account_info(accounts_iter)?;
  40. let token_program = next_account_info(accounts_iter)?;
  41. // Find the size for the account with the Extension
  42. let space = ExtensionType::get_account_len::<Mint>(&[ExtensionType::TransferFeeConfig]);
  43. // Get the required rent exemption amount for the account
  44. let rent_required = Rent::get()?.minimum_balance(space);
  45. // Create the account for the Mint and allocate space
  46. msg!("Mint account address : {}", mint_account.key);
  47. invoke(
  48. &system_instruction::create_account(
  49. payer.key,
  50. mint_account.key,
  51. rent_required,
  52. space as u64,
  53. token_program.key,
  54. ),
  55. &[
  56. mint_account.clone(),
  57. payer.clone(),
  58. system_program.clone(),
  59. token_program.clone(),
  60. ],
  61. )?;
  62. // The max fee will be 5 tokens, here we adjust it with the tokens decimals
  63. let max_fee = 5 * 10u64.pow(args.token_decimals as u32);
  64. // This needs to be done before the Mint is initialized
  65. // Initialize the Transfer Fee config
  66. invoke(
  67. &initialize_transfer_fee_config(
  68. token_program.key,
  69. mint_account.key,
  70. Some(payer.key),
  71. Some(payer.key),
  72. // 1% fee on transfers
  73. 100,
  74. max_fee,
  75. )
  76. .unwrap(),
  77. &[
  78. mint_account.clone(),
  79. token_program.clone(),
  80. payer.clone(),
  81. system_program.clone(),
  82. ],
  83. )?;
  84. // Initialize the Token Mint
  85. invoke(
  86. &token_instruction::initialize_mint(
  87. token_program.key,
  88. mint_account.key,
  89. mint_authority.key,
  90. Some(mint_authority.key),
  91. args.token_decimals,
  92. )?,
  93. &[
  94. mint_account.clone(),
  95. mint_authority.clone(),
  96. token_program.clone(),
  97. rent.clone(),
  98. ],
  99. )?;
  100. // Initialize the Transfer Fee config
  101. invoke(
  102. &set_transfer_fee(
  103. token_program.key,
  104. mint_account.key,
  105. payer.key,
  106. &[payer.key],
  107. // 10% fee on transfers
  108. 1000,
  109. max_fee,
  110. )
  111. .unwrap(),
  112. &[
  113. mint_account.clone(),
  114. token_program.clone(),
  115. payer.clone(),
  116. system_program.clone(),
  117. ],
  118. )?;
  119. msg!("Mint created!");
  120. Ok(())
  121. }