Lamport Dust Remediation
How to fix lamport dust exploitation vulnerabilities.
Lamport Dust Remediation
Overview
Related Detector: Lamport Dust
Lamport dust exploits programs that use exact equality on balances or fail to handle tiny residuals from rounding. The fix is to use inequality comparisons (<=, >=) instead of exact equality, zero both lamports and data on account closure, and round in favor of the protocol when calculating fees or distributions.
Recommended Fix
Before (Vulnerable)
// Vulnerable: exact equality allows dust bypass
if account.lamports() == 0 {
return Err(ProgramError::AccountAlreadyClosed);
}
After (Fixed)
// Fixed: use inequality and clear all data on close
let balance = account.lamports();
require!(balance > 0, ProgramError::AccountAlreadyClosed);
**recipient.lamports.borrow_mut() += balance;
**account.lamports.borrow_mut() = 0;
account.data.borrow_mut().fill(0); // Prevent resurrection
Alternative Mitigations
Anchor close Attribute
In Anchor programs, use the close attribute which handles lamport transfer and data zeroing automatically:
#[derive(Accounts)]
pub struct CloseVault<'info> {
#[account(mut, close = recipient)] // Transfers all lamports, zeros data
pub vault: Account<'info, Vault>,
#[account(mut)]
pub recipient: SystemAccount<'info>,
}
Common Mistakes
Mistake: Not Zeroing Account Data
// WRONG: transfers lamports but leaves data intact
**recipient.lamports.borrow_mut() += account.lamports();
**account.lamports.borrow_mut() = 0;
// Account data still has valid discriminator -- can be resurrected with 1 lamport
Mistake: Rounding Down User Withdrawals
// WRONG: truncation leaves dust in the protocol
let user_share = total_balance * user_tokens / total_supply;
// If user_tokens = 1 and total_supply = 3, user gets 0 -- dust stays in protocol
Round in the user’s favor on withdrawal, or accumulate remainders in a dedicated dust account.