I'm new to Solana and I'm trying to implement a multisig wallet with transfer SOL functionality. Basically I followed the implementation from this repo.

The problem is when I try to invoke my transfer function:

pub fn transfer_funds( ctx:Context<Transfer>,amount:u64) -> Result<()> {
  let amount_of_lamports = amount;
  let from = ctx.accounts.from.to_account_info();
  let to = ctx.accounts.to.to_account_info();

  **from.try_borrow_mut_lamports()? -= amount_of_lamports;
  **to.try_borrow_mut_lamports()? += amount_of_lamports;


From the execute transaction function:

pub fn execute_transaction(ctx: Context<ExecuteTransaction>) -> Result<()> {
  msg!("Executing Transaction");
  if ctx.accounts.transaction.did_execute {
    return Err(ErrorCode::AlreadyExecuted.into());

  let sig_count = ctx
    .filter(|&did_sign| *did_sign)
    .count() as u64;

  if sig_count < ctx.accounts.wallet.threshold {
    return Err(ErrorCode::NotEnoughSigners.into());

  let mut ix: Instruction = (*ctx.accounts.transaction).deref().into();
  ix.accounts = ix
    .map(|acc| {
      let mut acc = acc.clone();
      if &acc.pubkey == ctx.accounts.wallet_signer.key {
        acc.is_signer = true;

    let wallet_key = ctx.accounts.wallet.key();
    let seeds = &[wallet_key.as_ref(), &[ctx.accounts.wallet.nonce]];
    let signer = &[&seeds[..]];
    let accounts = ctx.remaining_accounts;
    solana_program::program::invoke_signed(&ix, accounts, signer)?;

    ctx.accounts.transaction.did_execute = true;
    emit!(TransactionExecutedEvent {
      wallet: ctx.accounts.wallet.key(),
      transaction: ctx.accounts.transaction.key(),


I get the Error: Transaction simulation failed Error processing Instruction insufficient account keys for instruction

I can, without problems, execute the set_owners and change_threshold functions.

My transaction for the transfer looks like this:

const [walletSigner] = await web3.PublicKey.findProgramAddress(
  [new PublicKey(state.connection.msig).toBuffer()],
let data;
try {
  data = state.connection.program.coder.instruction.encode(
      amount: new BN(args.amount),
} catch (err) {

const accounts = [
    pubkey: mustisigPublicKey,
    isWritable: true,
    isSigner: false,
    pubkey: walletSigner,
    isWritable: false,
    isSigner: true,
const transaction = web3.Keypair.generate();
const tx = await state.connection.program.rpc.createTransferTransaction(
    accounts: {
      wallet: mustisigPublicKey,
      transaction: transaction.publicKey,
      initiator: state.connection.provider.wallet.publicKey,
      to: args.to,
      from: mustisigPublicKey,
      systemProgram: web3.SystemProgram.programId,
    instructions: [
      await state.connection.program.account.wallet.createInstruction(
    signers: [transaction],

I'm guessing that this is related somehow to the accounts context not being forwarded to transfer function, but as I'm a complete beginner I cant be sure :/

  • I'm voting to close this question because it both contains too much and not enough clarity (eg. the definition of the Transfer struct is missing). If this is still relevant a year later, try to clarify the problem and give just enough detail for someone to spot the problem. Commented Dec 28, 2023 at 21:58


Browse other questions tagged or ask your own question.