Skip to main content
Sigvex

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.

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. an account-validation framework 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

References