Skip to main content
added 31 characters in body
Source Link
use anchor_lang::{
    prelude::*,
    solana_program::{
        program::invoke, system_instruction::create_account, system_instruction::transfer,
    },
};

// use anchor_lang::system_program::{create_account, CreateAccount};

declare_id!("5bZeT4cdAQH8dN2WW9s2kdzMzxy5oJX4hTProBaSazEn");

pub const PROGRAM_PUBKEY: &str = "program_seed";
pub const TIP_SEED: &str = "tip";

#[error_code]
pub enum TipError {
    #[msg("The tip has already been claimed.")]
    AlreadyClaimed,
}

#[program]
mod tip {
    use super::*;

    pub fn init(_ctx: Context<InitMaster>) -> Result<()> {
        Ok(())
    }

    pub fn give_tip(ctx: Context<GiveTip>, amount: u64) -> Result<()> {
        let tip = &mut ctx.accounts.tip;
        let sender = &ctx.accounts.sender;
        let system_program = &ctx.accounts.system_program;
        let pub_key = &tip.key();

        msg!("Program invoked. Creating a system account...");
        msg!("New public key will be: {}", tip.key().to_string());

        // Ensure the tip hasn't been claimed already
        if tip.amount > 0 {
            return Err(TipError::AlreadyClaimed.into());
        }

        // The minimum lamports for rent exemption
        let lamports = (Rent::get()?).minimum_balance(0);
        msg!("Minimum lamports for rent exemption: {}", lamports);

        invoke(
            &create_account(sender.key, pub_key, lamports, 0, system_program.key),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                system_program.to_account_info(),
            ],
        )?;

        msg!("Account created successfully.");

        // Transfer SOL to Tip PDA
        invoke(
            &transfer(&sender.key(), &tip.key(), amount),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                ctx.accounts.system_program.to_account_info(),
            ],
        ).map_err(|e| {
            msg!("Error transferring SOL: {}", e);
            e
        })?;

        tip.amount = amount;
        Ok(())
    }
 }

#[derive(Accounts)]
pub struct InitMaster {}
 

#[derive(Accounts)]
#[instruction(receiver:Pubkey,amount: u64)]
pub struct GiveTip<'info> {
    #[account( 
         init_if_needed,
     payer = sender,
     space = 8 + 32 + 8 + 1,
     seeds = ["program_seed".as_bytes(), &receiver.to_bytes() ,"tip".as_bytes()],
     bump,
 )]
    pub tip: Account<'info, Tip>,
    #[account(mut)]
    pub sender: Signer<'info>,
    pub system_program: Program<'info, System>,
}
 

#[account]
pub struct Tip {
    pub to: Pubkey,
    pub amount: u64,
}

use anchor_lang::{
    prelude::*,
    solana_program::{
        program::invoke, system_instruction::create_account, system_instruction::transfer,
    },
};

// use anchor_lang::system_program::{create_account, CreateAccount};

declare_id!("5bZeT4cdAQH8dN2WW9s2kdzMzxy5oJX4hTProBaSazEn");

pub const PROGRAM_PUBKEY: &str = "program_seed";
pub const TIP_SEED: &str = "tip";

#[error_code]
pub enum TipError {
    #[msg("The tip has already been claimed.")]
    AlreadyClaimed,
}

#[program]
mod tip {
    use super::*;

    pub fn init(_ctx: Context<InitMaster>) -> Result<()> {
        Ok(())
    }

    pub fn give_tip(ctx: Context<GiveTip>, amount: u64) -> Result<()> {
        let tip = &mut ctx.accounts.tip;
        let sender = &ctx.accounts.sender;
        let system_program = &ctx.accounts.system_program;
        let pub_key = &tip.key();

        msg!("Program invoked. Creating a system account...");
        msg!("New public key will be: {}", tip.key().to_string());

        // Ensure the tip hasn't been claimed already
        if tip.amount > 0 {
            return Err(TipError::AlreadyClaimed.into());
        }

        // The minimum lamports for rent exemption
        let lamports = (Rent::get()?).minimum_balance(0);
        msg!("Minimum lamports for rent exemption: {}", lamports);

        invoke(
            &create_account(sender.key, pub_key, lamports, 0, system_program.key),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                system_program.to_account_info(),
            ],
        )?;

        msg!("Account created successfully.");

        // Transfer SOL to Tip PDA
        invoke(
            &transfer(&sender.key(), &tip.key(), amount),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                ctx.accounts.system_program.to_account_info(),
            ],
        ).map_err(|e| {
            msg!("Error transferring SOL: {}", e);
            e
        })?;

        tip.amount = amount;
        Ok(())
    }
 }

#[derive(Accounts)]
pub struct InitMaster {}
 

#[derive(Accounts)]
#[instruction(amount: u64)]
pub struct GiveTip<'info> {
    #[account( 
         init_if_needed,
     payer = sender,
     space = 8 + 32 + 8 + 1,
     seeds = ["program_seed".as_bytes(),  "tip".as_bytes()],
     bump,
 )]
    pub tip: Account<'info, Tip>,
    #[account(mut)]
    pub sender: Signer<'info>,
    pub system_program: Program<'info, System>,
}
 

#[account]
pub struct Tip {
    pub to: Pubkey,
    pub amount: u64,
}

use anchor_lang::{
    prelude::*,
    solana_program::{
        program::invoke, system_instruction::create_account, system_instruction::transfer,
    },
};

// use anchor_lang::system_program::{create_account, CreateAccount};

declare_id!("5bZeT4cdAQH8dN2WW9s2kdzMzxy5oJX4hTProBaSazEn");

pub const PROGRAM_PUBKEY: &str = "program_seed";
pub const TIP_SEED: &str = "tip";

#[error_code]
pub enum TipError {
    #[msg("The tip has already been claimed.")]
    AlreadyClaimed,
}

#[program]
mod tip {
    use super::*;

    pub fn init(_ctx: Context<InitMaster>) -> Result<()> {
        Ok(())
    }

    pub fn give_tip(ctx: Context<GiveTip>, amount: u64) -> Result<()> {
        let tip = &mut ctx.accounts.tip;
        let sender = &ctx.accounts.sender;
        let system_program = &ctx.accounts.system_program;
        let pub_key = &tip.key();

        msg!("Program invoked. Creating a system account...");
        msg!("New public key will be: {}", tip.key().to_string());

        // Ensure the tip hasn't been claimed already
        if tip.amount > 0 {
            return Err(TipError::AlreadyClaimed.into());
        }

        // The minimum lamports for rent exemption
        let lamports = (Rent::get()?).minimum_balance(0);
        msg!("Minimum lamports for rent exemption: {}", lamports);

        invoke(
            &create_account(sender.key, pub_key, lamports, 0, system_program.key),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                system_program.to_account_info(),
            ],
        )?;

        msg!("Account created successfully.");

        // Transfer SOL to Tip PDA
        invoke(
            &transfer(&sender.key(), &tip.key(), amount),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                ctx.accounts.system_program.to_account_info(),
            ],
        ).map_err(|e| {
            msg!("Error transferring SOL: {}", e);
            e
        })?;

        tip.amount = amount;
        Ok(())
    }
 }

#[derive(Accounts)]
pub struct InitMaster {}
 

#[derive(Accounts)]
#[instruction(receiver:Pubkey,amount: u64)]
pub struct GiveTip<'info> {
    #[account( 
     init_if_needed,
     payer = sender,
     space = 8 + 32 + 8 + 1,
     seeds = ["program_seed".as_bytes(), &receiver.to_bytes() ,"tip".as_bytes()],
     bump,
 )]
    pub tip: Account<'info, Tip>,
    #[account(mut)]
    pub sender: Signer<'info>,
    pub system_program: Program<'info, System>,
}


#[account]
pub struct Tip {
    pub to: Pubkey,
    pub amount: u64,
}

Source Link

Cross-program invocation with unauthorized signer or writable account: Solana Tip Program

I'm building a Solana Anchor program for a tipping dApp, but I'm encountering an error. Can anyone assist me in troubleshooting and fixing the give_tip function?"

use anchor_lang::{
    prelude::*,
    solana_program::{
        program::invoke, system_instruction::create_account, system_instruction::transfer,
    },
};

// use anchor_lang::system_program::{create_account, CreateAccount};

declare_id!("5bZeT4cdAQH8dN2WW9s2kdzMzxy5oJX4hTProBaSazEn");

pub const PROGRAM_PUBKEY: &str = "program_seed";
pub const TIP_SEED: &str = "tip";

#[error_code]
pub enum TipError {
    #[msg("The tip has already been claimed.")]
    AlreadyClaimed,
}

#[program]
mod tip {
    use super::*;

    pub fn init(_ctx: Context<InitMaster>) -> Result<()> {
        Ok(())
    }

    pub fn give_tip(ctx: Context<GiveTip>, amount: u64) -> Result<()> {
        let tip = &mut ctx.accounts.tip;
        let sender = &ctx.accounts.sender;
        let system_program = &ctx.accounts.system_program;
        let pub_key = &tip.key();

        msg!("Program invoked. Creating a system account...");
        msg!("New public key will be: {}", tip.key().to_string());

        // Ensure the tip hasn't been claimed already
        if tip.amount > 0 {
            return Err(TipError::AlreadyClaimed.into());
        }

        // The minimum lamports for rent exemption
        let lamports = (Rent::get()?).minimum_balance(0);
        msg!("Minimum lamports for rent exemption: {}", lamports);

        invoke(
            &create_account(sender.key, pub_key, lamports, 0, system_program.key),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                system_program.to_account_info(),
            ],
        )?;

        msg!("Account created successfully.");

        // Transfer SOL to Tip PDA
        invoke(
            &transfer(&sender.key(), &tip.key(), amount),
            &[
                sender.to_account_info(),
                tip.to_account_info(),
                ctx.accounts.system_program.to_account_info(),
            ],
        ).map_err(|e| {
            msg!("Error transferring SOL: {}", e);
            e
        })?;

        tip.amount = amount;
        Ok(())
    }
 }

#[derive(Accounts)]
pub struct InitMaster {}
 

#[derive(Accounts)]
#[instruction(amount: u64)]
pub struct GiveTip<'info> {
    #[account( 
         init_if_needed,
     payer = sender,
     space = 8 + 32 + 8 + 1,
     seeds = ["program_seed".as_bytes(),  "tip".as_bytes()],
     bump,
 )]
    pub tip: Account<'info, Tip>,
    #[account(mut)]
    pub sender: Signer<'info>,
    pub system_program: Program<'info, System>,
}
 

#[account]
pub struct Tip {
    pub to: Pubkey,
    pub amount: u64,
}