Skip to main content
Sigvex

Lamport Conservation

Detects lamport conservation violations where balances are not properly maintained.

Lamport Conservation

Overview

The lamport conservation detector identifies patterns where lamports may not be properly conserved during transfers and CPI operations. While the Solana runtime enforces conservation at the transaction level, individual instructions can violate conservation invariants in ways that enable exploitation within multi-instruction transactions.

For remediation guidance, see Lamport Conservation Remediation.

Why This Is an Issue

The Solana runtime guarantees total lamport conservation across an entire transaction, but individual program instructions can create intermediate states where lamport invariants are violated. An attacker composing a multi-instruction transaction can exploit these intermediate violations – for example, one instruction credits lamports to the attacker’s account without proper debiting, and the attacker uses those lamports before a corrective instruction executes.

How to Resolve

Before (Vulnerable)

// Vulnerable: credits without validating debit
pub fn process_reward(accounts: &[AccountInfo], reward: u64) -> ProgramResult {
    let vault = &accounts[0];
    let user = &accounts[1];
    **vault.lamports.borrow_mut() -= reward;
    **user.lamports.borrow_mut() += reward;
    Ok(())
}

After (Fixed)

// Fixed: validates conservation invariant
pub fn process_reward(accounts: &[AccountInfo], reward: u64) -> ProgramResult {
    let vault = &accounts[0];
    let user = &accounts[1];

    require!(vault.lamports() >= reward, ProgramError::InsufficientFunds);
    let total_before = vault.lamports() + user.lamports();

    **vault.lamports.borrow_mut() -= reward;
    **user.lamports.borrow_mut() += reward;

    let total_after = vault.lamports() + user.lamports();
    require!(total_before == total_after, ProgramError::InvalidArgument);
    Ok(())
}

Example JSON Finding

{
  "detector": "lamport-conservation",
  "severity": "high",
  "confidence": 0.65,
  "message": "Lamport transfer without conservation invariant check across accounts",
  "location": { "function": "process_reward", "block": 0, "statement": 4 }
}

Detection Methodology

  1. Lamport operation tracking: Collects all lamport transfer operations and CPI calls that modify account balances.
  2. Balance flow analysis: Tracks debit and credit operations to verify that lamports leaving one account arrive at another.
  3. CPI interaction analysis: Flags CPI calls that modify account balances without corresponding balance checks in the caller.
  4. Conservation invariant verification: Checks for explicit pre/post balance comparisons around lamport-moving operations.

Limitations

False positives: Programs that intentionally burn lamports (fee collection where residual is discarded) will be flagged. False negatives: Conservation violations spanning multiple instructions in a transaction are not detected at single-function level.

References