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.
On Ethereum, every state change is implicitly gated by msg.sender. On Solana, the signer set is explicit — a transaction names every signer, and programs check is_signer on the accounts they care about. This design produces the 'authority pattern': every account has an authority field (the pubkey allowed to act on it), and programs verify that the correct authority signed the current transaction. This is the bedrock of Solana access control. Forget the signer check and you have a catastrophic bug — this is the #1 cause of Solana hacks.
A token mint has a mint_authority. Only a transaction signed by that authority can mint. The SPL Token program verifies this on every call. If you build your own program with a similar pattern, you must emit the same check — Anchor's has_one = authority constraint does this for you, but you can also write it manually. Failing to check is how protocols lose $20M.
// Anchor program with authority pattern
use anchor_lang::prelude::*;
#[program]
pub mod vault {
use super::*;
pub fn withdraw(ctx: Context<Withdraw>, amount: u64) -> Result<()> {
// has_one = authority is checked by the Anchor macro BEFORE this runs
**ctx.accounts.vault.to_account_info().try_borrow_mut_lamports()? -= amount;
**ctx.accounts.recipient.to_account_info().try_borrow_mut_lamports()? += amount;
Ok(())
}
}
#[account]
pub struct Vault { pub authority: Pubkey, pub balance: u64 }
#[derive(Accounts)]
pub struct Withdraw<'info> {
#[account(mut, has_one = authority)]
pub vault: Account<'info, Vault>,
pub authority: Signer<'info>, // MUST be a signer
#[account(mut)] pub recipient: AccountInfo<'info>,
}
// If Anchor's has_one check is removed OR authority is not a Signer,
// ANYONE can drain the vault by passing the real authority's pubkey
// (without signing) plus their own recipient. This is the bug that drained
// multiple Solana protocols in 2022–2023.
cargo runhas_one = authority and changes authority: Signer to authority: AccountInfo. Deploy it. Show that a non-authority can drain the vault. Then fix it. Record the audit finding in a markdown note.has_one, signer, address, owner, constraint = expr. For each, write a one-line example. Understand what each guards against.Sysvar::Instructions sysvar — programs can introspect the transaction to verify the instruction context. Note when you'd use this (e.g., enforce a preceding instruction like a priority-fee payment).Use these three in order. Each builds on the one before.
In one paragraph, explain the authority pattern on Solana — what an authority is, why programs store it in the account data, and what signer check enforces it.
Walk me through what happens when a Solana transaction is submitted that tries to drain a vault: how the runtime parses signers, how Anchor's `has_one` and `Signer` constraints are checked, and where in the call stack an unauthorised caller is rejected.
I'm designing a protocol where the 'authority' on high-risk accounts should be a 2-of-3 multisig, and on low-risk accounts should be a single key. How do I structure the authority field and the program checks to support both, and what are the upgrade paths when an authority needs to rotate?