Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Solana programs hold ONLY code — they have no storage of their own. All data lives in accounts that the caller passes in. This forces an explicit, declarative dataflow: you must enumerate every account a transaction touches up front. That declaration is what enables Solana's parallel execution model (you'll see this in M2).
A minimal Anchor program that holds a counter.
use anchor_lang::prelude::*;
declare_id!("Counter11111111111111111111111111111111111");
#[program]
pub mod counter {
use super::*;
pub fn increment(ctx: Context<Increment>) -> Result<()> {
let counter = &mut ctx.accounts.counter;
counter.value = counter.value.checked_add(1).unwrap();
Ok(())
}
}
// The program's code lives in the program account.
// The COUNTER VALUE lives in a separate account (PDA or user-owned).
#[derive(Accounts)]
pub struct Increment<'info> {
#[account(mut)]
pub counter: Account<'info, Counter>,
}
#[account]
pub struct Counter {
pub value: u64,
}
// To call increment, the user submits a tx with:
// - program_id: <Counter program pubkey>
// - accounts: [counter_account_pubkey]
// - data: <serialized "increment" instruction>
// The program code reads/writes counter_account's data field.
// The program itself stores nothing across invocations.