Search code examples
rustanchorsolana

How to reference a specific account in Solana programs with multiple accounts?


This program allows users to make an account to receive money. So 'Alice' can create the account Fundraiser. In Fundraiser, there is a specific variable amount_raised which keeps track of how much SOL has been sent to her account. This program allows for multiple people to create new Fundraisers..SO, how do I reference the correct account in the function 'donate'? I am suspecting that I need to use PDAs or at least iterate through all of the programs accounts and match it to the creator's pubkey. Thank you in advance. (Sol is sent in client, I just want to keep track of the amount_raised by adding the amount).

use super::*;

pub fn donate(ctx: Context<Donate>, amount: u32) -> ProgramResult {
    let fundraiser: &mut Account<Fundraiser> = &mut ctx.accounts.fundraiser;
    let user: &Signer = &ctx.accounts.user;
    fundraiser.amount_raised += amount;
    Ok(())
}


pub fn start_fund(ctx: Context<StartFund>, amount: u32, reason: String) -> ProgramResult {
    let fundraiser: &mut Account<Fundraiser> = &mut ctx.accounts.fundraiser;
    let author: &Signer = &ctx.accounts.author;
    let clock: Clock = Clock::get().unwrap();

    if reason.chars().count() > 350 {
        return Err(ErrorCode::ContentTooLong.into())
    }

    fundraiser.author = *author.key;
    fundraiser.amount_to_raise = amount;     
    fundraiser.timestamp = clock.unix_timestamp;
    fundraiser.reason = reason;
    Ok(())
}    

pub struct StartFund<'info> {
#[account(init, payer = author, space = 64 + 64)]
pub fundraiser: Account<'info, Fundraiser>,
#[account(mut)]
pub author: Signer<'info>,
#[account(address = system_program::ID)]
pub system_program: AccountInfo<'info>,
}    

#[derive(Accounts)]
pub struct Donate<'info> {
    #[account(mut)]
    pub fundraiser: Account<'info, Fundraiser>,
    #[account(mut)]
    pub user: Signer<'info>,
    #[account(address = system_program::ID)]
    pub system_program: AccountInfo<'info>,
    }        

#[account]
pub struct Fundraiser { 
 pub author: Pubkey,
 pub amount_to_raise: u32,
 pub amount_raised: u32,
 pub timestamp: i64,
 pub reason: String, //reason
}

} `


Solution

  • You've pretty much got it right -- in your Donate instruction, you'll also need to pass in Alice's author account, so that you can move transfer funds from user to author during Donate. So instead, it'll look something like:

    #[derive(Accounts)]
    pub struct Donate<'info> {
        #[account(mut)]
        pub fundraiser: Account<'info, Fundraiser>,
        #[account(mut)]
        pub user: Signer<'info>,
        #[account(mut)]
        pub author: AccountInfo<'info>,
        #[account(address = system_program::ID)]
        pub system_program: AccountInfo<'info>,
    }
    

    And you'll have to check that the author provided matches fundraiser.author.