Skip to main content
Sigvex

Zero Amount Operation Remediation

How to fix missing zero-amount validation in token operations.

Zero Amount Operation Remediation

Overview

Related Detector: Zero Amount Operation

Missing zero-amount validation allows token operations with zero values, which can bypass fee logic, cause accounting errors, or enable griefing. The fix adds explicit non-zero checks before token operations.

Before (Vulnerable)

pub fn transfer(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    // No amount validation -- zero is accepted
    spl_token::instruction::transfer(..., amount)?;
    Ok(())
}

After (Fixed)

pub fn transfer(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    if amount == 0 {
        return Err(ProgramError::InvalidArgument);
    }

    spl_token::instruction::transfer(..., amount)?;
    Ok(())
}

Alternative Mitigations

1. an account-validation framework constraint

pub fn transfer(ctx: Context<Transfer>, amount: u64) -> Result<()> {
    require!(amount > 0, ErrorCode::InvalidAmount);
    // ...
}

2. Minimum amount threshold

const MIN_TRANSFER_AMOUNT: u64 = 1000; // Minimum meaningful amount

pub fn transfer(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    if amount < MIN_TRANSFER_AMOUNT {
        return Err(ProgramError::Custom(ErrorCode::AmountBelowMinimum as u32));
    }
    // ...
}

3. Fee-aware minimum

Ensure the amount exceeds the fee so the net amount is positive:

let fee = calculate_fee(amount);
require!(amount > fee, ErrorCode::AmountTooSmallForFee);

Common Mistakes

Mistake 1: Checking amount after fee deduction only

// WRONG: fee might equal amount, making net = 0
let net = amount - fee;
require!(net > 0); // Should also check: require!(amount > 0) first

Mistake 2: Using >= 0 instead of > 0

// WRONG: u64 is always >= 0, this check is meaningless
require!(amount >= 0); // Always true for unsigned integers
// CORRECT:
require!(amount > 0);

References