Lamport Token Confusion Remediation
How to fix confusion between native SOL and SPL token operations.
Lamport Token Confusion Remediation
Overview
Related Detector: Lamport Token Confusion
Confusing native SOL (lamports) with SPL tokens causes incorrect decimal conversions and arithmetic errors. The fix requires clearly separating lamport and token operations and using correct conversion constants.
Recommended Fix
Before (Vulnerable)
// Wrong divisor and mixed operations
let sol_ui = account.lamports() / 1_000_000; // Wrong! SOL has 9 decimals
let total = sol_ui + token_amount; // Mixing different scales!
After (Fixed)
use solana_program::native_token::LAMPORTS_PER_SOL;
// Correct divisor
let sol_ui = account.lamports() / LAMPORTS_PER_SOL; // 1_000_000_000
// Convert to common scale before combining
let token_ui = token_amount / 10u64.pow(token_decimals as u32);
// Only combine values in the same unit (e.g., both in UI amounts or both in USD)
Alternative Mitigations
1. Use named constants
const LAMPORTS_PER_SOL: u64 = 1_000_000_000;
const USDC_DECIMALS: u8 = 6;
const USDC_SCALE: u64 = 1_000_000;
// Clear and self-documenting
let sol_amount = lamports / LAMPORTS_PER_SOL;
let usdc_amount = raw_usdc / USDC_SCALE;
2. Type-safe wrappers
Create distinct types to prevent mixing:
struct Lamports(u64);
struct TokenAmount { raw: u64, decimals: u8 }
// Compiler prevents: Lamports(x) + TokenAmount { ... }
3. Separate lamport and token processing functions
Never mix lamport and token logic in the same function to avoid confusion.
Common Mistakes
Mistake 1: Using 10^6 for SOL
// WRONG: SOL uses 9 decimals, not 6
let sol = lamports / 1_000_000;
// CORRECT: LAMPORTS_PER_SOL = 1_000_000_000
let sol = lamports / LAMPORTS_PER_SOL;
Mistake 2: Adding lamports to token amounts
// WRONG: different units
let total = account.lamports() + token_account.amount;
// These are in completely different scales
Mistake 3: Using account.lamports() for token balance
// WRONG: lamports is SOL balance, not token balance
let token_balance = token_account_info.lamports(); // This is SOL, not tokens!
// CORRECT:
let token_data = Account::unpack(&token_account_info.data.borrow())?;
let token_balance = token_data.amount;