Insufficient Lamport Balance
Detects lamport operations without sufficient balance validation.
Insufficient Lamport Balance
Overview
The insufficient lamport balance detector identifies lamport transfer or adjustment operations that do not validate sufficient balance before execution. Missing balance validation can cause transaction failures mid-execution, denial-of-service by draining accounts to zero, unexpected behavior in rent-exempt calculations, and account closure failures.
For remediation guidance, see Insufficient Lamport Balance Remediation.
Why This Is an Issue
Lamport transfers that exceed available balance will underflow, causing a runtime panic or wrapping to a very large value (depending on whether checked arithmetic is used). Even if the Solana runtime catches this, the failure occurs mid-instruction after some state may have already been modified. An attacker can exploit this by draining an account’s lamports through another instruction in the same transaction, then calling a function that assumes sufficient balance, causing unexpected failures or enabling denial-of-service.
How to Resolve
Before (Vulnerable)
// Vulnerable: no balance check before transfer
pub fn withdraw(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
let vault = &accounts[0];
let user = &accounts[1];
**vault.lamports.borrow_mut() -= amount; // Underflow if insufficient
**user.lamports.borrow_mut() += amount;
Ok(())
}
After (Fixed)
// Fixed: validate balance before transfer
pub fn withdraw(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
let vault = &accounts[0];
let user = &accounts[1];
require!(vault.lamports() >= amount, ProgramError::InsufficientFunds);
let rent = Rent::get()?;
let min_balance = rent.minimum_balance(vault.data_len());
require!(
vault.lamports() - amount >= min_balance,
ProgramError::InsufficientFunds
);
**vault.lamports.borrow_mut() -= amount;
**user.lamports.borrow_mut() += amount;
Ok(())
}
Example JSON Finding
{
"detector": "insufficient-lamport-balance",
"severity": "high",
"confidence": 0.7,
"message": "Lamport transfer without prior balance validation",
"location": { "function": "withdraw", "block": 0, "statement": 3 }
}
Detection Methodology
- Transfer operation identification: Locates all lamport transfer statements and CPI calls that move lamports.
- Balance check search: Scans preceding statements for comparison operations on the source account’s lamport balance.
- Rent-exempt awareness: Checks whether the validation accounts for rent-exempt minimum balance, not just zero.
- Checked arithmetic detection: Identifies whether the subtraction uses checked arithmetic or raw subtraction.
Limitations
False positives: Programs that validate balance in a separate setup function called before the transfer function may be flagged. False negatives: Balance checks using complex conditional logic across multiple functions may not be detected.
Related Detectors
- Lamport Conservation — detects conservation violations
- Lamport Dust — detects dust-related issues
- Unchecked Fee Rent Math — detects rent calculation errors