Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
An Ethereum project usually deploys many contracts (factory, pool, governance, etc.). A Solana project usually deploys one program that handles many instruction variants. This design forces tight modularity within a single binary and a different upgrade model — programs are upgradable via BPF Loader Upgradeable, not by deploying new contracts.
A Solana program with multiple instructions.
solana program show <PROGRAM_ID> — note the upgrade authority and the program data account.Use these three in order. Each builds on the one before.
In one paragraph, explain how a Solana program differs from an Ethereum contract.
Walk me through how the BPF Loader Upgradeable handles program upgrades.
Compare the security model of 'program upgrade authority' (Solana) to 'proxy admin' (Ethereum). Which is harder to abuse and why?
use anchor_lang::prelude::*;
declare_id!("MyD3F1ProgramAddressHere11111111111111111111");
#[program]
pub mod my_defi {
use super::*;
pub fn initialize_pool(ctx: Context<InitPool>) -> Result<()> { /* ... */ Ok(()) }
pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> { /* ... */ Ok(()) }
pub fn withdraw(ctx: Context<Withdraw>, shares: u64) -> Result<()> { /* ... */ Ok(()) }
pub fn swap(ctx: Context<Swap>, amount_in: u64, min_out: u64) -> Result<()> { /* ... */ Ok(()) }
pub fn liquidate(ctx: Context<Liquidate>) -> Result<()> { /* ... */ Ok(()) }
}
// Each instruction is dispatched by an 8-byte discriminator (sha256("global:method_name"))
// Programs are upgraded by re-uploading the binary; upgrade authority must sign.
// No proxy patterns needed — upgrade is built into the BPF loader.
#[derive(Accounts)]
pub struct InitPool<'info> { /* accounts */ }
#[derive(Accounts)]
pub struct Deposit<'info> { /* accounts */ }
// ... etc