I'm an EVM smart contract developer and new to solana. I'm trying to implement a program in solana where users can deposit/withdraw SOL to participate in a bet. How can I implement a payable like functionality where users can send SOL while calling an instruction.

This is the code I currently have

fn transfer_sol<'a>(
    signer: &AccountInfo<'a>,
    recepient: &AccountInfo<'a>,
    amount: u64,
) -> ProgramResult {
    // Create the system transfer instruction
    let transfer_instruction = system_instruction::transfer(signer.key, recepient.key, amount);

    msg!("Transferring from {} to {}", signer.key, recepient.key);

    // Send the transfer instruction
        &[signer.clone(), recepient.clone(), system_program],

    msg!("Transferred {} SOL", amount);


when I run this code, I keep getting this error

Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account

Do I need to include some account in the account_info array for this to work

  • 1
    Make sure to check that the recipient is what you are expecting and the users are not just passing in their own address. Just a tip, it's a common pitfall.
    – Jonas H.
    Jan 2 at 0:38

1 Answer 1


You’ll have to make sure that both the sending and receiving account are marked as mut on the client side.

If you’re using anchor, you can do this by annotating the account field with the #[account(mut)] attribute. This reflects in the IDL and generated client scaffold, and marks that account as mutable.

Otherwise, if you’re building your project without anchor, make sure that when constructing your client-side instruction, the AccountMeta objects for those accounts have their isMutable fields set to true.

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.