SECURITY

10 Most Common Smart Contract Vulnerabilities — With Code Examples

A comprehensive guide to the most common smart contract vulnerabilities with code examples and prevention strategies.

Read time

3 min

Category

Security

FAQ

0

Quick summary

A comprehensive guide to the most common smart contract vulnerabilities with code examples and prevention strategies.

Author

ClickMasters Team

Published

2025-06-23

Book a Call

Need a quick expert recommendation?

Get a practical recommendation before you spend weeks choosing the wrong blockchain architecture.

Book a Free Strategy Call

Complete Comparison

The most common smart contract vulnerabilities include reentrancy, integer overflow/underflow, access control issues, oracle manipulation, flash loan attacks, unchecked external call returns, delegatecall to untrusted contracts, griefing (gas limit DoS), front-running, and price impact manipulation. Each vulnerability has specific prevention patterns.

1. Reentrancy

Before all state updates, an external call allows the callee to call back into the function. Classic: withdraw() calls the user before zeroing the balance — user re-enters withdraw() repeatedly.

Prevention: OpenZeppelin ReentrancyGuard. CEI (Checks-Effects-Interactions) pattern.

2. Integer Overflow/Underflow

Pre-Solidity 0.8: arithmetic wraps silently. 255 + 1 = 0 for uint8. `unchecked` blocks in 0.8+: still vulnerable.

Prevention: Use Solidity 0.8+. Avoid `unchecked` for user-controlled values.

3. Access Control (Missing Modifier)

`function mint(address to, uint256 amount) external { _mint(to, amount); }` — anyone can mint.

Prevention: OpenZeppelin Ownable, AccessControl. Every privileged function needs a modifier.

4. Oracle Manipulation

Reading spot price from a single DEX — flash loan can manipulate it within one transaction.

Prevention: TWAP oracles, Chainlink + TWAP dual-oracle.

5. Flash Loan Attacks

Borrowing uncollateralized capital to amplify attack: manipulate oracle, exploit governance, drain lending pool.

Prevention: Require multi-block consistency for price-sensitive operations. Flash loan-proof design.

6. Unchecked External Call Returns

`addr.call{value: amount}(""); // Return value ignored` If the call fails silently, the state has already been updated.

Prevention: Always check return value: `(bool success,) = addr.call{...}(...); require(success);`

7. Delegatecall to Untrusted Contract

In proxy patterns: if the implementation address can be set by untrusted parties, they can execute arbitrary code in the proxy's storage context.

Prevention: Strict access control on upgradeability. Never delegatecall to user-supplied addresses.

8. Griefing (Gas Limit DoS)

A function iterates over an unbounded array. Attacker fills the array with 10,000 elements. The function now costs more gas than the block limit: permanently unusable.

Prevention: Limit array growth. Use pagination for large iterations. Pull-over-push pattern.

9. Front-Running

Attacker observes pending transaction in mempool, inserts their own transaction with higher gas to execute first. DEX sandwich attacks are the canonical example.

Prevention: Commit-reveal scheme. Flashbots bundles. Slippage limits. Private mempool.

10. Price Impact Manipulation (ERC-777 / Callback Issues)

ERC-777 tokens have a transfer hook that calls the recipient before updating balances. Protocols that integrated ERC-777 as if it were ERC-20 were vulnerable to reentrancy via the hook.

Prevention: Use ERC-20 only in DeFi. Treat any external call as a potential reentrancy vector.

Need Help Securing Your Smart Contracts?

Get expert guidance on smart contract security and vulnerability prevention.

Book a Free Strategy Call