सामग्री पर जाएँ

Learning in Public: Solana Smart Contracts Development

Learning in Public: Solana Smart Contracts Development

Hello this will be a quite different article where i share my notes while studying some topic/framework/language/technology in this section we will cover Solana Smart Contracts. So without any further ado let's get started!

Solana's high level overview

It's a opensource permissionless blockchain, that uses the unit of account as "SOL and Lamports. 1 Lamport = 0.000000001 SOL".

Approximately 1500 nodes capable of 50k TPS. Implements a number of real enhancements to achieve this level of thorughput

Useful link: https://medium.com/solana-labs/7-innovations-that-make-solana-the-first-web-scale-blockchain-ddc50b1defda

  • Comprised of multiple clusters:
    • Devnet
    • Testnet
    • Mainnet Beta
    • Localnet / Test Validator Node
  • Uses a BFT PoS (Proof of Stake) concensus mechanism and PoH (Proof of History) to maintain the state

Solana Smart Contracts x Account: Two total different things

  1. Smart Contracts

Solana is a total new concept of writing smart contracts so different than Ethereum that the contracts are Stateful solana uses a Stateless approach so the contracts only holds the logic and nothing more than that. And also each contract deployed has a Program Id that is the address/account the program is stored in.

  1. Accounts

So as we mentioned above the smart contract is stored inside the account and to store state. To create a state the smart contract need to create other accounts to store that data and the only one that can change the account is the user that holds the seed for that account, this is thanks for the PoH (Proof of History) that we mentioned above.

So Knowing that we can assume that:

  • Account is actually a buffer
  • Can be thought of like a Operating System File
  • Includes metadata that tells the runtime who is allowed to access the data and how
  • Held in Validator memory to pay the 'rent' to stay
    • So In Solana the state from a Smart Contract get's stored into the account
    • And users needs to be payed a 'rent' so the file can be kept into storage

Solana Instructions

So as we know the accounts store the state and the contract stores only the logic but how we can change the state? So different than Ethereum the state is not on the contract and as i mentioned above the accounts will hold a state inside a buffer, and to interact with the accounts you need to pass a instruction with the accounts that you guys are interacting with:

Like this:

# Instruction 1
ProgramID: ...
Accounts: [Acct1, Acct2]
Data: [1,2,3,4,5,6]

# Instruction 2
ProgramID: ...
Accounts: [Acct3, Acct4]
Data: [9,8,7,6,5,4]

# Transaction 1
[Instruction1, Instruction2]

So as we saw above a instruction os a conjunction of accounts, programID and also the data that is pretty much a ByteArray that is used to send input data to the on-chain programs written in Rust/C

This is the instruction Flow for the solana Blockchain:

Economics and Rent

Here goes a little bit of the complexity of Solana's Economics/Storage,

  • Validators get paid transactions fees + inflationary rewards
  • Stakers are rewarded for helping validate the ledger by delegating their stake to validator nodes
  • Inflation currently set to Approximately 8%
  • Each transaction submitted to the ledger imposes costs
    • Tx Fees only covers processing the transaction, not storing it long term

As we told above accounts have a cost for existing regular accounts are covered by the fees but when it comes to storage comes into a whole new thing! So in solana we can pay to register data into the storage through other accounts and we pay that 'rent' fee that we mentioned above where we can pay and store to the on-chain data

  • Storage Rent covers the cost of storing data in Accounts over time
  • 2 Methods of storage rent:
    • Set and Forget
    • Pay per Byte

Data Serialization

Differently than Ethereum to interact with a Smart contract or a Program on the Solana blockchain you need to serialize that data into Bytes and deserialize into the smart contract!

  • Serialization/Serialize: Converting an object in memory to a stream of Bytes
  • Deserialization/Deserialize: Converting a stream of Bytes into a readable object in memory

So to send our data to/from a program via the JSON RPC requires serialization and deserialization

Anchor: Solana's Sealevel runtime framework

Anchor is a framework created by Armani Ferrante, to quickly build secure Solana Programs, it reduces the coding effort by generating various boilerplate's of code

Anchor's Workflow:

Anchor's Sample Code:

use anchor_lang::prelude::*;

// The Address that this program is Located At
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");


// Business Logic and new will go here with the initalize function
#[program]
pub mod raffle {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        Ok(())
    }
}

// Validate the accounts for the initialize method
#[derive(Accounts)]
pub struct Initialize {}

Anchor Accounts

  • Where you define which accounts your instruction expects, and which constraints these accounts should follow
    • Types: Mostly Rust defined structs that derives from the #[account] macro
    #[account]
    #[derive(Default)]
    pub struct MyAccount {
        data: u64,
        mint: Pubkey
    }
    
    • Constraints
      • you can use the same macro to define the account constraints example: #[account(mut)]

Read more about the constraints and safety checks here: https://www.anchor-lang.com/docs/the-accounts-struct

Anchor's Program

In rust anchor we have the part of the program that we call program where all the functions are defined. As we can see in the example below

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
        ctx.accounts.my_account.data = data;
        Ok(())
    }
}
  • The ctx parameter is the deserialized accounts object
  • We can add parameters as arguments to the function as we saw above we have a parameter called data that is a additional parameter added
    • Anchor will automatically deserialize the instruction data into the arguments types so this way we can add parameters as String, Array and etc...

Anchor IDL: Interface Description Language

  • Generates a IDL specification for the programs
    • Similar to the EVM-based Abi
  • Used by clients to be able to interact with deployed Anchor-based programs
  • Greatly simplifies calling functions, sending and receiving data
  • Acts as the connecting glue between on-chain program, and off chain clients

Lets make a simple contract

So now we are going to create a simple contract where we can set a Greeting message to a user

Before we start please follow the installation process on the anchor documentation: https://www.anchor-lang.com/docs/installation

NOTE: IF YOU ARE RUNNING ON APPLE SILICON DEVICES AND HAD ANY PROBLEM WHILE INSTALLING SOLANA CHECK THIS ARTICLE HERE

  1. First let's initialize our project by running the following command anchor init greeting-anchor, this command will generate a base anchor project for us with a skeleton smart contract with tests passing
  2. Let's build our rust code inside programs > greeting-anchor > src > lib.rs
use anchor_lang::prelude::*;

// ID for our solana program
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
pub mod greeting_anchor {
  use super::*;

  // The function that will mutate the state of the greeting Account, with the message parameter
  pub fn set_message(ctx: Context<SetMessage>, message: String) -> Result<()> {
    let greeting_account = &mut ctx.accounts.greeting;
    greeting_account.greeting = message;
    msg!("Greeting updated, {}", greeting_account.greeting);
    Ok(())
  }
}

#[account]
struct GreetingAccount {
  // Greeting message for that account
  pub greeting: String,
}

#[derive(Accounts)]
pub struct SetMessage<'info> {
  // The account that will be initialized by Solana to store our Contract State
  // Here we are describint that this account will be initialized and that the one that will be paying for this account is the user
  #[account(init, payer = user, space = 8 + 32)]
  greeting: Account<'info, GreetingAccount>,

  // The user account that will sign the transaction
  #[account(mut)]
  pub user: Signer<'info>,

  // default for every instruction to include the system program from solana
  pub system_program: Program<'info, System>,
}
  1. Let's write tests for our solana smart contract under tests > greeting-anchor.ts
import * as anchor from "@project-serum/anchor";
import { Program } from "@project-serum/anchor";
import { assert } from "chai";
import { GreetingAnchor } from "../target/types/greeting_anchor";

describe("greeting-anchor", () => {
  const provider = anchor.AnchorProvider.env();
  // Configure the client to use the local cluster.
  anchor.setProvider(provider);

  const program: Program<GreetingAnchor> = anchor.workspace.GreetingAnchor;

  it("should execute the function call without any issues", async () => {
    const greetingAccount = anchor.web3.Keypair.generate();

    await program.methods
      .setMessage("Hello World")
      .accounts({
        greetingAccount: greetingAccount.publicKey,
        user: provider.publicKey,
        systemProgram: anchor.web3.SystemProgram.programId,
      })
      .signers([greetingAccount])
      .rpc({
        commitment: "confirmed",
      });

    const { greeting } = await program.account.greetingAccount.fetch(
      greetingAccount.publicKey,
    );

    assert(greeting === "Hello World", "Error Unexpected message");
  });
});
  1. Run anchor test to be sure that everything is working fine and you have successfuly written your first smart contract using Rust + Solana

NOTE: I've got an issue by using the latest anchor version and it was not generating the account structs on the IDL so just use the 0.24.2 that is working fine

Useful Links

Hope that the information helps!

Profile picture
Luiz Fernando - सीनियर सॉफ़्टवेयर इंजीनियर

पढ़ने के लिए धन्यवाद!

आशा है यह लेख आपको पसंद आया। सवाल या प्रतिक्रिया हो तो सोशल मीडिया पर लिखें। आपका दिन शुभ हो!

Carousel imageCarousel imageCarousel imageCarousel imageCarousel image
आगे / अच्छी चीज़ बातचीत से शुरू होती है

बड़े विचार।
Little Luiz.

कोई उत्पाद जीवित करना है? कोई टीम मज़बूत करनी है? देखें हम साथ क्या बना सकते हैं।

अपना रास्ता चुनें
01Freelance / Products

मेरे पास एक प्रोजेक्ट है

फ़्रीलांस सहयोग, उत्पाद और तकनीकी चुनौतियाँ।

  • उत्पाद खोज से डिलीवरी तक
  • वेब, मोबाइल और बैकएंड इंजीनियरिंग
  • स्पष्ट स्कोप। सीधा सहयोग।
कुछ साथ बनाएँ
02Hiring / Teams

मैं टीम बना रहा हूँ

इंजीनियरिंग भूमिकाएँ और लंबे अवसर।

  • सीनियर फ़ुल-स्टैक इंजीनियरिंग
  • उत्पाद सोच और तकनीकी स्वामित्व
  • वितरित टीमों का अनुभव
अपनी टीम में शामिल करें
03Résumé / Versions

रिज़्यूमे देखें

सामान्य इंजीनियरिंग, हेल्थ-टेक, फ़िनटेक और अधिक के लिए तैयार संस्करण।

  • छह केंद्रित रूप
  • प्रिंट-तैयार PDF
  • हर भूमिका के लिए अपडेट
मेरा रिज़्यूमे पढ़ें
luizepauloxd@gmail.com

ईमेल पसंद है? सीधे लिखें, या यहाँ ड्राफ़्ट शुरू करें।

बताएँ आपके मन में क्या है।

© 2026 Luiz Fernando इरादे से बना। और थोड़ी जिज्ञासा से।ऊपर जाएँ