Dinaiscoding
Dinaiscoding

Reputation: 1388

Solana can't mint to a different token account

Folks, I'm starting with Solana and it's been rough to learn. Despite the poor error messages and the learning curve of Rust, I'm making my way through it.

I'm trying to develop a new token that will be a fungible asset (0 decimals, supply greater than 1 for the same token).

In another transaction, I already created a mint account and initialized it. Now I'm trying to mint that to another wallet. Basically, this is mint accounts context (for simplicity reasons I've excluded the metadata accounts):

pub struct MintAsset<'info> {
    #[account(mut)]
    pub mint: Account<'info, token::Mint>,
    #[account(mut)]
    pub mint_authority: Signer<'info>,
    /// CHECK: We're about to create this with Anchor
    #[account(mut)]
    pub minter_token: UncheckedAccount<'info>,
    #[account(mut)]
    pub payer: Signer<'info>,
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, token::Token>,
    pub associated_token_program: Program<'info, associated_token::AssociatedToken>,
}

Then, I proceed to run this transaction for minting my tokens

pub fn mint_asset(ctx: Context<MintAsset>, data: MintArgs) -> Result<()> {   
        associated_token::create(
            CpiContext::new(
                ctx.accounts.associated_token_program.to_account_info(),
                associated_token::Create {
                    payer: ctx.accounts.mint_authority.to_account_info(),
                    associated_token: ctx.accounts.minter_token.to_account_info(),
                    authority: ctx.accounts.mint_authority.to_account_info(),
                    mint: ctx.accounts.mint.to_account_info(),
                    system_program: ctx.accounts.system_program.to_account_info(),
                    token_program: ctx.accounts.token_program.to_account_info(),
                    rent: ctx.accounts.rent.to_account_info(),
                },
            ),
        )?;

        token::mint_to(
            CpiContext::new(
                ctx.accounts.token_program.to_account_info(),
                token::MintTo {
                    mint: ctx.accounts.mint.to_account_info(),
                    to: ctx.accounts.minter_token.to_account_info(),
                    authority: ctx.accounts.mint_authority.to_account_info(),
                },
            ),
            data.amount,
        )?;

        Ok(())
    }

By using the following test:

async function mintToken(
    program: anchor.Program<Pdas>,
    wallet: anchor.Wallet,
    mintKeypair: anchor.web3.Keypair,
    minterWallet: anchor.Wallet,
    amount: number
  ) {
    try {
      
      const buyerTokenAddress = await anchor.utils.token.associatedAddress({
        mint: mintKeypair.publicKey,
        owner: wallet.publicKey,
      });
  
      const accounts = {
        mint: mintKeypair.publicKey,
        mintAuthority: wallet.publicKey,
        minterToken: buyerTokenAddress,
        payer: wallet.publicKey,
      };
  
      const signers = [];
  
      const args = {
        amount: new BN(amount),
      };
  
      const signature = await program.methods
        .mintAsset(args)
        .accounts(accounts)
        .signers(signers)
        .rpc();
    } catch (error) {
      console.log("MINT ERROR:", inspect({ error }, { depth: null }));
    }
  }

Now, that test throws an error if for the buyerTokenAddress I use the minterWallet as owner. I understand that for owning a token, one must have an associated token account, which, as stated by the documentation, is an

account for a given wallet address is simply a program-derived account consisting of the wallet address itself and the token mint

https://spl.solana.com/associated-token-account

Why's that? I mean, doesn't anyone can mint a this token? I understand that only the mintAuthority can mint the tokens, but it makes sense to have it as a signer (as accounts struct expect), but (and here's another question) if I put an empty array of signers, the code still runs (again, why is that? I thought I had to provide an signer account at least for mint_authority).

Should I create a new mint account and initialize it? Wouldn't that be a new token, instead?

What is obvious in Solana token development that I'm missing here? Thanks in advance

Upvotes: 0

Views: 1130

Answers (1)

Naveed Ali
Naveed Ali

Reputation: 101

I may not be able to answer your first question properly, so I'm leaving that for someone more experienced. For your second question you are right about signer, as you are using anchor it implicitly takes owner wallet from configuration (anchor.toml file) and signs it. if you provide your wallet.key in signer array there will be no difference. because anchor does that so generally that isn't provided in signers[]

Upvotes: 0

Related Questions