SPL Token Delegation Overflow Remediation
How to fix integer overflow vulnerabilities in token delegation amount calculations.
SPL Token Delegation Overflow Remediation
Overview
Related Detector: SPL Token Delegation Overflow
Integer overflow in delegation amount calculations can produce incorrect approval amounts, potentially allowing delegates to drain entire accounts. The fix requires using checked arithmetic for all amount calculations and validating results against account balances.
Recommended Fix
Before (Vulnerable)
let amount = base * multiplier; // Can overflow!
spl_token::instruction::approve(..., amount)?;
After (Fixed)
let amount = base
.checked_mul(multiplier)
.ok_or(ProgramError::ArithmeticOverflow)?;
let balance = Account::unpack(&token_account.data.borrow())?.amount;
require!(amount <= balance, ErrorCode::InsufficientBalance);
spl_token::instruction::approve(..., amount)?;
Alternative Mitigations
1. Saturating arithmetic
When overflow should cap at the maximum rather than error:
let amount = base.saturating_add(additional);
// amount is capped at u64::MAX instead of wrapping
2. Anchor constraint validation
#[account(constraint = delegation_amount <= token_account.amount @ ErrorCode::Overflow)]
pub token_account: Account<'info, TokenAccount>,
3. Pre-computed constants
If amounts are known at compile time, use constants to avoid runtime arithmetic:
const MAX_DELEGATION: u64 = 1_000_000_000; // Pre-computed, no overflow risk
Common Mistakes
Mistake 1: Using wrapping arithmetic
// WRONG: wrapping_add silently wraps on overflow
let amount = base.wrapping_add(additional);
// CORRECT: checked_add returns None on overflow
let amount = base.checked_add(additional).ok_or(Error)?;
Mistake 2: Not validating against balance after calculation
// INCOMPLETE: checked arithmetic prevents overflow but not over-delegation
let amount = base.checked_add(additional)?;
// Missing: require!(amount <= token_account.amount)
Mistake 3: Using bit shifts for token amount scaling
// RISKY: left shift can silently lose high bits
let amount = base << decimals; // Use checked_shl or explicit multiplication