◂ 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
next labSYSVAR ADDRESS CHECKING ▸