Input Validation

The process of verifying that user-supplied data meets expected formats and constraints before processing, preventing injection attacks and logic errors.

Input validation is a fundamental security practice that verifies user-supplied data meets expected formats, types, and constraints before the application processes it. In both smart contracts and web applications, failing to validate inputs can lead to critical vulnerabilities including injection attacks, integer overflows, unauthorized access, and logic errors. Proper input validation is the first line of defense against many common attack vectors.

Why Input Validation Matters

Without validation, attackers can supply malicious inputs:

1// VULNERABLE: No validation
2function transfer(address to, uint256 amount) external {
3 balances[msg.sender] -= amount;
4 balances[to] += amount;
5}
6
7// Attack vectors:
8// - to = address(0) → tokens lost forever
9// - amount > balance → underflow (pre-0.8.0)
10// - to = msg.sender → self-transfer issues

Smart Contract Input Validation

Address Validation

1function setRecipient(address _recipient) external {
2 require(_recipient != address(0), "Zero address");
3 require(_recipient != address(this), "Cannot be self");
4 recipient = _recipient;
5}

Amount Validation

1function deposit(uint256 amount) external {
2 require(amount > 0, "Zero amount");
3 require(amount <= maxDeposit, "Exceeds max");
4 require(amount >= minDeposit, "Below min");
5 // Process deposit
6}

Array Validation

1function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) external {
2 require(recipients.length == amounts.length, "Length mismatch");
3 require(recipients.length > 0, "Empty array");
4 require(recipients.length <= MAX_BATCH, "Too many recipients");
5
6 for (uint256 i = 0; i < recipients.length; i++) {
7 require(recipients[i] != address(0), "Zero address in batch");
8 _transfer(recipients[i], amounts[i]);
9 }
10}

Bounds Checking

1function setFee(uint256 _fee) external onlyOwner {
2 require(_fee <= MAX_FEE, "Fee too high"); // e.g., MAX_FEE = 1000 (10%)
3 fee = _fee;
4}
5
6function setIndex(uint256 _index) external {
7 require(_index < array.length, "Index out of bounds");
8 currentIndex = _index;
9}

Web Application Input Validation

TypeScript/JavaScript

1function validateAddress(address: string): boolean {
2 return /^0x[a-fA-F0-9]{40}$/.test(address);
3}
4
5function validateAmount(amount: string): boolean {
6 const num = parseFloat(amount);
7 return !isNaN(num) && num > 0 && num <= MAX_AMOUNT;
8}
9
10// Express.js middleware
11function validateTransferInput(req, res, next) {
12 const { to, amount } = req.body;
13
14 if (!validateAddress(to)) {
15 return res.status(400).json({ error: 'Invalid address' });
16 }
17 if (!validateAmount(amount)) {
18 return res.status(400).json({ error: 'Invalid amount' });
19 }
20
21 next();
22}

Sanitization vs Validation

Validation: Check if input is acceptable, reject if not

1if (!isValidEmail(email)) {
2 throw new Error('Invalid email');
3}

Sanitization: Transform input to safe format

1import DOMPurify from 'dompurify';
2const safeHtml = DOMPurify.sanitize(userInput);

Both are needed—validate first, then sanitize if accepting.

Common Validation Patterns

Whitelist vs Blacklist

1// WEAK: Blacklist (blocks known bad)
2function isValidInput(input: string): boolean {
3 const blacklist = ['<script>', 'javascript:', 'onerror'];
4 return !blacklist.some(bad => input.includes(bad));
5}
6
7// STRONG: Whitelist (allows known good)
8function isValidInput(input: string): boolean {
9 return /^[a-zA-Z0-9\s]+$/.test(input); // Only alphanumeric
10}

Whitelisting is preferred—it's secure by default.

Type Coercion Safety

1// DANGEROUS: Implicit conversion
2const amount = Number(userInput); // "123abc" → 123
3
4// SAFER: Strict parsing with validation
5function parseAmount(input: string): number {
6 if (!/^\d+(\.\d+)?$/.test(input)) {
7 throw new Error('Invalid number format');
8 }
9 return parseFloat(input);
10}

Validation Libraries

Solidity

Use modifiers for reusable validation:

1modifier validAddress(address _addr) {
2 require(_addr != address(0), "Invalid address");
3 _;
4}
5
6modifier validAmount(uint256 _amount) {
7 require(_amount > 0 && _amount <= MAX, "Invalid amount");
8 _;
9}
10
11function transfer(address to, uint256 amount)
12 external
13 validAddress(to)
14 validAmount(amount)
15{
16 // Logic here
17}

TypeScript

1import { z } from 'zod';
2
3const TransferSchema = z.object({
4 to: z.string().regex(/^0x[a-fA-F0-9]{40}$/),
5 amount: z.number().positive().max(1000000),
6 memo: z.string().max(256).optional()
7});
8
9function validateTransfer(data: unknown) {
10 return TransferSchema.parse(data); // Throws on invalid
11}

Input Validation in DeFi

Price/Rate Validation

1function setPrice(uint256 _price) external onlyOracle {
2 require(_price > 0, "Zero price");
3 require(_price <= MAX_PRICE, "Price too high");
4
5 // Sanity check against last price
6 if (lastPrice > 0) {
7 uint256 change = diff(_price, lastPrice) * 100 / lastPrice;
8 require(change <= MAX_CHANGE, "Price change too large");
9 }
10
11 lastPrice = _price;
12}

Slippage Parameters

1function swap(uint256 amountIn, uint256 minAmountOut) external {
2 require(minAmountOut > 0, "Min output zero");
3
4 uint256 amountOut = calculateOutput(amountIn);
5 require(amountOut >= minAmountOut, "Slippage exceeded");
6
7 // Execute swap
8}

Audit Checklist

When auditing input validation:

  • All external function parameters validated
  • Zero address checks on address inputs
  • Bounds checking on numeric inputs
  • Array length validation (non-zero, max length)
  • String length limits
  • Type-appropriate validation (addresses, amounts, IDs)
  • Whitelist approach over blacklist
  • Consistent validation across similar functions

Input validation is a foundational security practice that prevents entire classes of vulnerabilities. Always validate at the earliest point and never trust user input, regardless of its source.

Need expert guidance on Input Validation?

Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.

Get a Quote

oog
zealynx

Subscribe to Our Newsletter

Stay updated with our latest security insights and blog posts

© 2024 Zealynx