◂ labs
TIER 3 · LIFECYCLE & SYSVARS · 9-closing-accounts

CLOSING ACCOUNTS & REVIVAL

Marking an account closed (lamports → 0) is not enough: a later instruction in the same tx can "revive" it by refunding rent, leaving a zeroed-but-live account ready for reinit. The exit writeback stomps the zeroing — the pack confirmed revival survives every "fixed" variant.

seen in the wild
The pack found an inverted check in the "secure" variant of this lesson — a real upstream bug in the teaching repo itself.
rust · anchor
use anchor_lang::prelude::*;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

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

    pub fn close(ctx: Context<Close>) -> ProgramResult {
        let dest_starting_lamports = ctx.accounts.destination.lamports();

        **ctx.accounts.destination.lamports.borrow_mut() = dest_starting_lamports
            .checked_add(ctx.accounts.account.to_account_info().lamports())
            .unwrap();
        **ctx.accounts.account.to_account_info().lamports.borrow_mut() = 0;

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Close<'info> {
    account: Account<'info, Data>,
    destination: AccountInfo<'info>,
}

#[account]
pub struct Data {
    data: u64,
}
▸ the pack already hunted this class — watch the live feed of run_1789547662_fca40c