1

I'm pretty new solana ecosystem and have been following multiple tutorials on minting Fungible SPL tokens. On all the tutorials, you create a Mint and ATA and the then the first time the mint authority mints to the ATA (using mintTo) - it always works, but when you try and mintTo the same ATA again it always fails.

How can you mint multiple times to the same ATA?

I've been following code samples from the official docs, i.e: https://spl.solana.com/token

Here is my code:

// import custom helpers
import { payer, connection } from "@/lib/vars";
import {
  createMint,
  getMint,
  getOrCreateAssociatedTokenAccount,
  getAccount,
  mintTo,
} from "@solana/spl-token";

(async () => {
  // for simplicity, use same key for payer, mintAuthority and freezeAuthority and also as the account (+ ATA) to receive the token via mint
  const mintAuthority = payer.publicKey;
  const freezeAuthority = payer.publicKey;

  const mint = await createMint(connection, payer, mintAuthority, freezeAuthority, 18);
  console.log("Mint address: ", mint.toBase58()); // e.g. EiTNK33Fd7nruEsJmmtFkLp4CcbkpvjBnyE7beAcPNHR

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  const mintInfoBefore = await getMint(connection, mint);
  console.log("Mint current supply (before): ", mintInfoBefore.supply); // 0n

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  const tokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    payer,
    mint, // mint account
    payer.publicKey, // mint For
  );
  console.log("ATA address: ", tokenAccount.address.toBase58()); // e.g. EDmVHv2UrU96rZVV1nN5mio3dCXmqYBbZjy59T1YedKw

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  const tokenAccountInfo = await getAccount(connection, tokenAccount.address);
  console.log("ATA address amount (before): ", tokenAccountInfo.amount); // 0n

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  // 1st mint to ATA (WORKS!) - 10 tokens

  await mintTo(
    connection,
    payer,
    mint, // mint account
    tokenAccount.address, // mint for this ATA
    mintAuthority,
    10000000000000000000, // 10 tokens with 18 decimals
  );

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  const mintInfoAfter = await getMint(connection, mint);
  console.log("Mint current supply (after 1): ", mintInfoAfter.supply); // 10000000000000000000n

  const tokenAccountInfoAfter = await getAccount(connection, tokenAccount.address);
  console.log("ATA address amount (after 1): ", tokenAccountInfoAfter.amount); // 10000000000000000000n

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  // 2nd mint to same ATA (FAILS!)

  await mintTo(
    connection,
    payer,
    mint,
    tokenAccount.address,
    mintAuthority,
    10000000000000000000,
  );

  /*
    ERROR DETAILS:
    
    /Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5921
          throw new SendTransactionError(
                ^
    SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom program error: 0xe
        at Connection.sendEncodedTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5921:13)
        at processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async Connection.sendRawTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5880:20)
        at async Connection.sendTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5868:12)
        at async sendAndConfirmTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/utils/send-and-confirm-transaction.ts:35:21) {
      logs: [
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]',
        'Program log: Instruction: MintTo',
        'Program log: Error: Operation overflowed',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4326 of 200000 compute units',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: custom program error: 0xe'
      ]
    }
  */

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  const mintInfoAfter2 = await getMint(connection, mint);
  console.log("Mint current supply (after 2): ", mintInfoAfter2.supply);

  const tokenAccountInfoAfter2 = await getAccount(connection, tokenAccount.address);
  console.log("ATA address amount (after 2): ", tokenAccountInfoAfter2.amount);
})();

As you can see, the first mint to the ATA works, but when you try and call another mint on the same ATA it fails with the error:

    /Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5921
          throw new SendTransactionError(
                ^
    SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom program error: 0xe
        at Connection.sendEncodedTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5921:13)
        at processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async Connection.sendRawTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5880:20)
        at async Connection.sendTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/connection.ts:5868:12)
        at async sendAndConfirmTransaction (/Users/foobar/quest-1/node_modules/@solana/web3.js/src/utils/send-and-confirm-transaction.ts:35:21) {
      logs: [
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]',
        'Program log: Instruction: MintTo',
        'Program log: Error: Operation overflowed',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4326 of 200000 compute units',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: custom program error: 0xe'
      ]
    }

These are the package.json libs I'm using FYI:

    "@solana/spl-token": "^0.4.1",
    "@metaplex-foundation/js": "^0.20.1",
    "@metaplex-foundation/mpl-token-metadata": "^3.2.1",
    "@solana/web3.js": "^1.91.0",

Regardless on if I use the same ATA or even if I use a seperate ATA (for a seperate user) for the 2nd mint, I've noticed that I get the same error. It almost seems like you can only call mintTo 1 time for Mint?? But this can't be right

Any help will be appreciated?

Thanks all!

1 Answer 1

2

The token amount is stored in a u64, which can have max 18446744073709551615. Let's say 1.8e19.

With your first mintTo you are setting it to 1e19, which is less than 1.8e19, so there is no problem. When you add another 1e19, then the u64 overflows.

The log reports it as:

  'Program log: Error: Operation overflowed',
1
  • Yes, this was the issue. Thanks for the suggestion. I'm trying to bridge an 18 decimal ERC20 token with 1 billion supply to Solana (each token has 18 decimals). So it looks like this wont be directly possible (to the 18th decimal precision) on SPL given the u64 limitation. So, I'll have to figure out a different way to do this I suppose. Maybe limit the decimal precision allowed for SPL version of the token. Commented Mar 10 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.