• Discover
  • Partner with us
  • Chapters
  • Blog

Learn everything about Solana

Course Introduction
Solana Introduction
Solana Smart Contract Fundamentals - Transactions
Solana Smart Contract Fundamentals - Instructions
Solana Smart Contract Fundamentals - Accounts
Solana Smart Contract Fundamentals - Program Derived Addresses (PDAs)

Installation Rust
Counter I - Implementing State and Instructions
Counter II - Implementing Process Instruction
Counter III - Build & Test
Submit Your Homework 1: Update Increment and Decrement Functions

Token Transfer I - Implementing process_instruction
Token Transfer II - Testing
Submit Your Homework 2: Change Transfer Amount

What Are We Going to Build?
Review I - Implementing State
Review II - Defining Instructions
Review III - Implementing Add_Review
Review IV - Implementing Update_Review
Review V - Build & Deploy
Review VI - Frontend

Build Your Final Project

In this lesson, we are going to see how we can create a review and store it.

Here is the changes we have made to lib.rs in this video:

pub mod instruction;
pub mod state;

use borsh::BorshSerialize;
use crate::instruction::ReviewInstruction;
use crate::state::AccountState;
use crate::state::ReviewError;
use solana_program::{
    account_info::{next_account_info, AccountInfo},
    borsh0_10::try_from_slice_unchecked,
    entrypoint,
    entrypoint::ProgramResult,
    msg,
    program::invoke_signed,
    program_error::ProgramError,
    program_pack::IsInitialized,
    pubkey::Pubkey,
    system_instruction,
    sysvar::{rent::Rent, Sysvar},
};
use std::convert::TryInto;

entrypoint!(process_instruction);

pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    let instruction = ReviewInstruction::unpack(instruction_data)?;
    match instruction {
        ReviewInstruction::AddReview {
            title,
            rating,
            description,
        } => add_review(program_id, accounts, title, rating, description),
        ReviewInstruction::UpdateReview {
            title,
            rating,
            description,
        } => update_review(program_id, accounts, title, rating, description),
    }
}

pub fn add_review(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    title: String,
    rating: u8,
    description: String,
) -> ProgramResult {
    msg!("Adding  review...");
    msg!("Title: {}", title);
    msg!("Rating: {}", rating);
    msg!("Description: {}", description);

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_account = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    let (pda, bump_seed) = Pubkey::find_program_address(
        &[initializer.key.as_ref(), title.as_bytes().as_ref()],
        program_id,
    );
    if pda != *pda_account.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    if rating > 10 || rating < 1 {
        return Err(ReviewError::InvalidRating.into());
    }

    let account_len: usize = 1000;

    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(account_len);

    invoke_signed(
        &system_instruction::create_account(
            initializer.key,
            pda_account.key,
            rent_lamports,
            account_len.try_into().unwrap(),
            program_id,
        ),
        &[
            initializer.clone(),
            pda_account.clone(),
            system_program.clone(),
        ],
        &[&[
            initializer.key.as_ref(),
            title.as_bytes().as_ref(),
            &[bump_seed],
        ]],
    )?;

    msg!("PDA created: {}", pda);

    msg!("unpacking state account");
    let mut account_data =
        try_from_slice_unchecked::<AccountState>(&pda_account.data.borrow()).unwrap();
    msg!("borrowed account data");

    msg!("checking if  account is already initialized");
    if account_data.is_initialized() {
        msg!("Account already initialized");
        return Err(ProgramError::AccountAlreadyInitialized);
    }

    account_data.title = title;
    account_data.rating = rating;
    account_data.description = description;
    account_data.is_initialized = true;

    msg!("serializing account");
    account_data.serialize(&mut &mut pda_account.data.borrow_mut()[..])?;
    msg!("state account serialized");

    Ok(())
}
Previous
Next

Lesson discussion

Swap insights and ask questions about “Learn everything about Solana”.

Enroll to participate
Start the course to unlock the discussion. Enrolling helps us keep conversations relevant to learners.
WebsiteDiscoverPartner with UsBlogEvents
Discover
CoursesCircleRustSoliditySolanaWeb3 FundamentalsBlockchain Basics
CompanyAbout UsBrand GuidelineFAQsTerms of UsePrivacy PolicyGDPR NoticeCookies
Don't miss any update!

Disclaimer: The information, programs, and events provided on https://risein.com is strictly for upskilling and networking purposes related to the technical infrastructure of blockchain platforms. We do not provide financial or investment advice, nor do we make any representations regarding the value, profitability, or future price of any blockchain or cryptocurrency. Users are encouraged to conduct their own research and consult with licensed financial professionals before engaging in any investment activities. https://risein.com disclaims any responsibility for financial decisions made by users based on the information provided here.

© 2026 Rise In, All rights reserved