1

I've been working on Solana program that should hold two different tokens for me in a Vault in an ATA. The first token should be deposited during Vault initialisation, the second will be deposited by exchanging for the first, will some fixed ratio. Both ATAs for the PDA of the Vault i wanted to be created during Vault initialisation. The problem is i keep getting error:

bundle.js:85 Error initializing vault: Error: Signature verification failed
    at Je.serialize (<anonymous>:3:173798)
    at AnchorProvider.sendAndConfirm (provider.ts:157:1)
    at async MethodsBuilder.rpc [as _rpcFn] (rpc.ts:29:1)
    at async initializeVault

The PDA initialisation looks fine, i was comparing it with lots of similar programs, tried debugging it, looks like the error is not related to fn initialize_vault but it's related to account creation. Here is an Anchor code:

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

    pub fn initialize_vault(ctx: Context<InitializeVault>, initial_heim_amount: u64) -> Result<()> {
        if ctx.accounts.authority_heim_ata.mint != mints::HEIM_ADDRESS {
            return Err(ProgramError::InvalidAccountData.into());
        }
        let vault = &mut ctx.accounts.vault;
        vault.authority = *ctx.accounts.authority.key;
        vault.heim_amount = initial_heim_amount;
        vault.usdc_amount = 0;

        let cpi_accounts = SplTransfer {
            from: ctx.accounts.authority_heim_ata.to_account_info().clone(),
            to: ctx.accounts.vault_heim_ata.to_account_info().clone(),
            authority: ctx.accounts.authority.to_account_info().clone()
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();

        token::transfer(CpiContext::new(cpi_program, cpi_accounts), initial_heim_amount)?;

        Ok(())
    }
}

#[account]
pub struct Vault {
    pub authority: Pubkey,
    pub heim_amount: u64,
    pub usdc_amount: u64,
    pub bump: u8,
}

#[derive(Accounts)]
pub struct InitializeVault<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,
    #[account(
        init,
        payer = authority,
        space = 8 + 64 + 32 + 1,
        seeds=[b"heim_vault".as_ref(), authority.key().as_ref()],
        bump
    )]
    pub vault: Account<'info, Vault>,
    #[account(
        init,
        payer = authority,
        associated_token::mint = heim_mint,
        associated_token::authority = authority,
    )]
    pub vault_heim_ata: Account<'info, TokenAccount>,
    pub heim_mint: Account<'info, Mint>,
    #[account(
        init,
        payer = authority,
        associated_token::mint = usdc_mint,
        associated_token::authority = authority,
    )]
    pub vault_usdc_ata: Account<'info, TokenAccount>,
    pub usdc_mint: Account<'info, Mint>,
    #[account(mut)]
    pub authority_heim_ata: Account<'info, TokenAccount>,
    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
    pub rent: Sysvar<'info, Rent>, // do i really need it here? google it
    pub associated_token_program: Program<'info, AssociatedToken>,
}

And this is the client-side:

const getProvider = () => {
    const connection = new Connection(network, opts.preflightCommitment)
    return new AnchorProvider(connection, window.solana, opts.preflightCommitment)
  }

  const initializeVault = async() => {
    try {
      const provider = getProvider()
      const program = new Program(idl, programID, provider)

      const heimMint = new PublicKey(
        "BVqRM5tbqerXFnGBSDZMvGEvdUx3aVNUadBiQBbjAjxB"
      );
      const usdcMint = new PublicKey(
        "NkHsgx5xBCPp6Gi33KTPgD2weVJJY884NiuVjz76APn"
      );
      const mintInfo = await provider.connection.getAccountInfo(heimMint)
      const data = MintLayout.decode(mintInfo.data);

      // eslint-disable-next-line no-unused-vars
      const [vault, _] = PublicKey.findProgramAddressSync(
        [
          utils.bytes.utf8.encode("heim_vault"),
          provider.wallet.publicKey.toBuffer()
        ],
        program.programId
      );

      const authorityHeimATA = await getAssociatedTokenAddress(heimMint, provider.wallet.publicKey);
      const vaultHeimATA = await getAssociatedTokenAddress(heimMint, vault, true);
      const vaultUsdcATA = await getAssociatedTokenAddress(usdcMint, vault, true);

      const heim_amount = new BN(1000).mul(new BN(10).pow(new BN(data.decimals)))
      const result = await program.methods.initializeVault(heim_amount).accounts(
        {
          authority: provider.wallet.publicKey,
          vault: vault,
          heimMint: heimMint,
          usdcMint: usdcMint,
          systemProgram: SystemProgram.programId,
          authorityHeimAta: authorityHeimATA,
          vaultHeimAta: vaultHeimATA,
          vaultUsdcAta: vaultUsdcATA,
          tokenProgram: TOKEN_PROGRAM_ID,
          associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
          rent: web3.SYSVAR_RENT_PUBKEY,
        }
      ).rpc()
      console.log("result", result)

      getVault();
    } catch (error) {
      console.error('Error initializing vault:', error)
    }
  }

If you guys could take a look at it that would be great. This is devnet code so usdc is a fake usdc.

1
  • You seem to be missing bump, on the TokenAccount init decorators.
    – Whiteseal
    Commented Apr 11 at 21:15

1 Answer 1

0

The error says it all: Error: Signature verification failed. There's only one signer in your instruction, which is authority. The code all looks correct, so maybe there's something incorrect with how the Provider is setup.

2
  • Provider is set up like that: ``` const programID = new PublicKey(idl.metadata.address); const network = clusterApiUrl("devnet"); const opts = { preflightCommitment: "processed", } const getProvider = () => { const connection = new Connection(network, opts.preflightCommitment) return new AnchorProvider(connection, window.solana, opts.preflightCommitment) } ``` This is set up the same way i did it for another, simpler project and it worked there . Commented Nov 14, 2023 at 17:16
  • The AnchorProvider constructor takes Connection, then Wallet, then ConfirmOptions. You're passing in window.solana as the Wallet, so that parameter might not be a real signer
    – Jon C
    Commented Nov 14, 2023 at 18:06

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.