DEV Community

Heemin Kim
Heemin Kim

Posted on • Originally published at contract-scanner.raccoonworld.xyz

Top 5 Solidity Vulnerabilities in 2026

Smart contract exploits cost the DeFi ecosystem over $1.7 billion in 2024, and the trend continued through 2025. Understanding the most common vulnerability patterns is the first step toward writing safer code.

1. Reentrancy Attacks

Reentrancy remains the most notorious smart contract vulnerability. An attacker can repeatedly call back into your contract before the first execution finishes, draining funds before balances are updated.

Vulnerable pattern:

function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount);
    (bool ok,) = msg.sender.call{value: amount}(""); // ← external call first
    require(ok);
    balances[msg.sender] -= amount; // ← state update too late
}
Enter fullscreen mode Exit fullscreen mode

Safe pattern (Checks-Effects-Interactions):

function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount; // ← update state first
    (bool ok,) = msg.sender.call{value: amount}("");
    require(ok);
}
Enter fullscreen mode Exit fullscreen mode

Use OpenZeppelin's ReentrancyGuard for an additional layer of protection.

2. Access Control Failures

Missing or misconfigured access controls accounted for the largest losses in 2024 ($953M). Critical functions left unprotected allow anyone to call them directly.

// ❌ No access control
function setAdmin(address newAdmin) external {
    admin = newAdmin;
}

// ✅ Protected
function setAdmin(address newAdmin) external onlyOwner {
    admin = newAdmin;
}
Enter fullscreen mode Exit fullscreen mode

Watch out for tx.origin checks — they can be bypassed via a malicious intermediary contract. Always use msg.sender.

3. Flash Loan Price Manipulation

Flash loans allow borrowing large sums within a single transaction. If your protocol reads price from an on-chain AMM spot price, an attacker can manipulate it momentarily to drain your treasury.

Prevention: Use time-weighted average prices (TWAP) from Uniswap v3, or a decentralized oracle like Chainlink.

4. Integer Overflow / Underflow

Pre-Solidity 0.8.0, arithmetic didn't revert on overflow. Many legacy contracts still run under older compiler versions.

// Solidity < 0.8.0, this wraps to type(uint).max
uint256 balance = 0;
balance -= 1; // ← underflows silently
Enter fullscreen mode Exit fullscreen mode

Fix: Use Solidity 0.8.x (safe math by default) or OpenZeppelin's SafeMath for older code.

5. Unprotected Initializers

Upgradeable proxy contracts often use initialize() instead of constructor(). If the initializer isn't protected with initializer modifier, an attacker can re-initialize the contract and take ownership.

// ❌ Callable by anyone, anytime
function initialize(address _owner) public {
    owner = _owner;
}

// ✅ One-time call enforced
function initialize(address _owner) public initializer {
    owner = _owner;
}
Enter fullscreen mode Exit fullscreen mode

How ContractScan Helps

ContractScan checks for all five of these vulnerability categories. Try the scanner on your next contract before deployment.

Top comments (0)