1

I have tried to transfer spl token from user account to program(contract) I wrote this contract with help of GPT have fixed many things now I stuck here with this error

My ultimate goal is to transfer money to contract then later from contract I should transfer it to some other wallets any help or any example?

solpg ERROR

Running client...
  client.ts:

    User ATA account: 3XNcYXdfZ5k1C6bFw3JeZD6zeChbbiyfKXkbs75tKo3G
    Vault PDA account: D3kGGFN28uqBrfyYPpAy2etZ9Jv1UjWuuEWKNJDWNZGB
$ 
    Error in main execution: { [Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Provided seeds do not result in a valid address]
  logs: 
   [ 'Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]',
     'Program log: Create',
     'Program log: Error: Associated address does not match seed derivation',
     'Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 8057 of 200000 compute units',
     'Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL failed: Provided seeds do not result in a valid address' ] }

$ 

lib.rs

use anchor_lang::prelude::*;
use anchor_lang::solana_program::entrypoint::ProgramResult;
use anchor_spl::token::{
    self, transfer_checked, Mint, Token, TokenAccount, TransferChecked as SPLTransferChecked,
};

declare_id!("7KNzQPbmGAN4G45ncYvmCbh3xpdaYzh2iyRbZRtUwkUV");

#[program]
pub mod deposit_and_release {
    use super::*;

    pub fn deposit(ctx: Context<Deposit>, amount: u64) -> ProgramResult {
        msg!("Deposit function called with amount: {}", amount);

        // Validate deposit amount
        if amount < 1_000_000 || amount > 10_000_000 {
            msg!("Invalid deposit amount: {}", amount);
            return Err(ProgramError::Custom(ErrorCode::InvalidDepositAmount as u32));
        }

        // Set up the CPI (cross-program invocation) context for the token transfer
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_accounts = SPLTransferChecked {
            from: ctx.accounts.depositor.to_account_info(),
            mint: ctx.accounts.usdc_mint.to_account_info(),
            to: ctx.accounts.vault.to_account_info(),
            authority: ctx.accounts.depositor.to_account_info(),
        };

        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);

        // Execute the token transfer
        transfer_checked(cpi_ctx, amount, ctx.accounts.usdc_mint.decimals)?;

        msg!(
            "Successfully transferred {} tokens from user's ATA to program's PDA vault.",
            amount
        );
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Deposit<'info> {
    #[account(mut)]
    pub depositor: Signer<'info>, // User wallet that authorizes the transfer
    #[account(mut, constraint = user_deposit.owner == depositor.key())]
    pub user_deposit: Account<'info, TokenAccount>, // User's associated token account (ATA)
    #[account(mut, seeds = [b"vault", usdc_mint.key().as_ref()], bump)]
    // Ensure PDA ownership by program
    pub vault: Account<'info, TokenAccount>, // PDA vault for receiving tokens
    pub usdc_mint: Account<'info, Mint>, // Token mint for USDC
    pub token_program: Program<'info, Token>, // Token program for the transfer
    pub system_program: Program<'info, System>, // System program
}

#[error_code]
pub enum ErrorCode {
    #[msg("Invalid deposit amount.")]
    InvalidDepositAmount,
}

client.ts

import anchor from "@project-serum/anchor";
import {
  Connection,
  PublicKey,
  SystemProgram,
  Transaction,
} from "@solana/web3.js";
import {
  TOKEN_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID,
  getAssociatedTokenAddress,
  createAssociatedTokenAccountInstruction,
} from "@solana/spl-token";

const solpg = pg;
const connection = solpg.connection;
const program = solpg.program;

async function main() {
  const usdcMintAddress = new PublicKey(
    "88vRvJtjbESDcQw8yDwGgu1HAotP6LPikpfp1UjsPy2K"
  );

  const wallet = solpg.wallet;
  const userPublicKey = wallet.publicKey;

  // Create user token account associated with USDC mint
  const userTokenAccount = await getAssociatedTokenAddress(
    usdcMintAddress,
    userPublicKey,
    false,
    TOKEN_PROGRAM_ID,
    ASSOCIATED_TOKEN_PROGRAM_ID
  );

  console.log("User ATA account:", userTokenAccount.toString());

  // Derive the PDA for the program-owned vault account
  const [vaultAccount, vaultBump] = await PublicKey.findProgramAddress(
    [Buffer.from("vault"), usdcMintAddress.toBuffer()],
    program.programId
  );

  console.log("Vault PDA account:", vaultAccount.toString());

  // Check if the vault account exists, if not, create it
  const vaultAccountInfo = await connection.getAccountInfo(vaultAccount);
  if (!vaultAccountInfo) {
    const transaction = new Transaction().add(
      createAssociatedTokenAccountInstruction(
        wallet.publicKey, // Payer
        vaultAccount, // ATA address
        program.programId, // Owner of the ATA (program PDA)
        usdcMintAddress, // Mint address
        TOKEN_PROGRAM_ID,
        ASSOCIATED_TOKEN_PROGRAM_ID
      )
    );

    // Send transaction to create the ATA
    await connection.sendTransaction(transaction, [wallet.keypair]);
    console.log("Vault ATA account created.");
  }

  // Define deposit amount (1 USDC with 6 decimals)
  const depositAmount = 1_000_000;

  // Call the deposit function from the program
  try {
    await program.rpc.deposit(new anchor.BN(depositAmount), {
      accounts: {
        depositor: userPublicKey,
        userDeposit: userTokenAccount,
        vault: vaultAccount,
        usdcMint: usdcMintAddress,
        tokenProgram: TOKEN_PROGRAM_ID,
        systemProgram: SystemProgram.programId,
      },
      signers: [],
    });

    console.log("Deposited 1 USDC into the vault!");
  } catch (error) {
    console.error("Transaction failed:", error);
  }
}

main().catch((err) => {
  console.error("Error in main execution:", err);
});

I believe I'm missing something, any help? thanks in advance!!

1 Answer 1

1

const transaction = new Transaction().add( createAssociatedTokenAccountInstruction( wallet.publicKey, // Payer vaultAccount, // ATA address program.programId, // Owner of the ATA (program PDA) usdcMintAddress, // Mint address TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID ) );

In this owner of the ata could not be the program. It can't own any ATA accounts. You have to Make a pda in the program, and Find the ATA of that PDA. like a Vault account, and find its ata like Vault ata

2
  • After suggested modification getting this error 'Program log: AnchorError caused by account: vault. Error Code: AccountNotInitialized. Error Number: 3012. Error Message: The program expected this account to be already initialized.', Commented Oct 30 at 8:08
  • You have to Initialize The vault account before hand, or have the init command on the vault account in the same instruction Commented Nov 1 at 4:19

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.