Token Decimal Mismatch
Detects token transfers and swaps with mismatched decimals without proper conversion.
Token Decimal Mismatch
Overview
Remediation Guide: How to Fix Token Decimal Mismatch
The token decimal mismatch detector identifies token operations (transfers, swaps) that involve tokens with different decimal places without proper conversion. On Solana, different SPL tokens use different decimal precisions — USDC uses 6 decimals while wrapped SOL uses 9. Without proper adjustment, a transfer of “1,000,000” raw units could represent 1 USDC or 0.001 wSOL, leading to catastrophic value miscalculations up to 1000x.
Why This Is an Issue
Token amounts on Solana are stored as raw u64 integers. The decimals field on the mint account defines how to interpret these raw values:
- 1 USDC (6 decimals) = 1,000,000 raw units
- 1 wSOL (9 decimals) = 1,000,000,000 raw units
- Without conversion: treating 1,000,000 USDC raw units as if they were 9-decimal tokens gives 0.001 instead of 1.0
This has caused significant losses in DeFi protocols where swap calculations, price feeds, or cross-token operations failed to account for decimal differences.
CWE mapping: CWE-682 (Incorrect Calculation).
How to Resolve
pub fn safe_swap(
accounts: &[AccountInfo], amount_in: u64,
) -> ProgramResult {
let mint_in = &accounts[0];
let mint_out = &accounts[1];
let decimals_in = Mint::unpack(&mint_in.data.borrow())?.decimals;
let decimals_out = Mint::unpack(&mint_out.data.borrow())?.decimals;
// Adjust for decimal difference
let amount_out = if decimals_out >= decimals_in {
let factor = 10u64.checked_pow((decimals_out - decimals_in) as u32)
.ok_or(ProgramError::ArithmeticOverflow)?;
amount_in.checked_mul(factor).ok_or(ProgramError::ArithmeticOverflow)?
} else {
let factor = 10u64.checked_pow((decimals_in - decimals_out) as u32)
.ok_or(ProgramError::ArithmeticOverflow)?;
amount_in.checked_div(factor).ok_or(ProgramError::ArithmeticOverflow)?
};
// Proceed with swap using adjusted amount
Ok(())
}
Examples
Vulnerable Code
pub fn swap(accounts: &[AccountInfo], amount_in: u64) -> ProgramResult {
// VULNERABLE: no decimal check or adjustment
let amount_out = calculate_price(amount_in);
transfer_tokens(accounts[0].clone(), accounts[1].clone(), amount_out)?;
Ok(())
}
Fixed Code
pub fn swap(accounts: &[AccountInfo], amount_in: u64) -> ProgramResult {
let mint_in_decimals = Mint::unpack(&accounts[2].data.borrow())?.decimals;
let mint_out_decimals = Mint::unpack(&accounts[3].data.borrow())?.decimals;
// Normalize to common precision before price calculation
let normalized = normalize_amount(amount_in, mint_in_decimals, mint_out_decimals)?;
let amount_out = calculate_price(normalized);
transfer_tokens(accounts[0].clone(), accounts[1].clone(), amount_out)?;
Ok(())
}
Sample Sigvex Output
{
"detector_id": "token-decimal-mismatch",
"severity": "critical",
"confidence": 0.80,
"description": "Token swap operation does not perform decimal adjustment between input and output tokens. If tokens have different decimal places, this results in incorrect price calculations.",
"location": { "function": "swap", "offset": 1 }
}
Detection Methodology
- Evidence collection: Tracks mint account decimal field reads, token-to-mint relationships, and decimal adjustment operations (multiplication/division by powers of 10).
- Transfer analysis: Identifies token transfer CPIs and checks whether both source and destination token accounts have corresponding decimal reads.
- Swap analysis: Identifies swap operations and verifies decimal adjustments are present nearby.
- Proximity analysis: Looks for decimal adjustment operations within a 5-statement window of the token operation.
Limitations
- Heuristic-based classification of transfers vs swaps may misidentify some operations.
- Decimal adjustments computed in separate helper functions may not be detected.
- Programs that only handle tokens with the same decimals may be false-positively flagged.
Related Detectors
- SPL Token Authority Confusion — detects use of Transfer instead of TransferChecked
- Integer Overflow — detects overflow in arithmetic operations