Common vulnerabilities

Smart contract bugs are permanent and often catastrophic. Know the attack surface before you deploy.

Why security is different on-chain

Traditional software bugs can be patched with a hotfix. Smart contracts are immutable — once deployed, the code runs forever exactly as written. A single bug can drain all funds in the contract in one transaction, and there's no rollback. This is why security isn't a final step — it's woven into every decision you make while writing Solidity.

The most common vulnerability classes

1. Reentrancy

A contract makes an external call before updating its own state. The external contract calls back into the original function before the state is updated, allowing repeated withdrawals.

This is covered in depth in the Reentrancy Attacks lesson.

2. Integer overflow and underflow

Before Solidity 0.8.0, arithmetic could silently wrap around. This is now handled automatically, but you'll encounter pre-0.8 contracts and patterns in the wild.

solidity
// Solidity < 0.8: this would silently overflow to 0
uint8 x = 255;
x += 1;  // x = 0 (silently!)

// Solidity >= 0.8: reverts with panic code 0x11
uint8 x = 255;
x += 1;  // reverts

3. Access control failures

Missing or incorrect visibility modifiers leave admin functions callable by anyone.

solidity
// VULNERABLE: no access control
function setOwner(address newOwner) public {
    owner = newOwner;  // anyone can call this!
}

// SAFE:
function setOwner(address newOwner) public onlyOwner {
    owner = newOwner;
}

4. Unchecked return values

Some older tokens return false on failure instead of reverting. If you don't check the return value, you'll think the transfer succeeded when it didn't.

solidity
// VULNERABLE: assumes success
token.transfer(to, amount);

// SAFE: use SafeERC20 from OpenZeppelin
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
using SafeERC20 for IERC20;
token.safeTransfer(to, amount);  // reverts if transfer fails

5. Front-running

Transactions are visible in the mempool before they're included in a block. Bots can observe a pending transaction and place their own transaction with higher gas to execute first — extracting value (MEV).

6. Oracle manipulation

Contracts that rely on on-chain prices (e.g., a single DEX pool as a price oracle) can be manipulated via flash loans within a single transaction.

The security mindset

  • Assume all inputs are hostile
  • Checks-Effects-Interactions pattern: validate first, update state second, make external calls last
  • Use well-audited libraries (OpenZeppelin) instead of rolling your own
  • Get an audit before deploying anything with real value
  • Write comprehensive tests including attack scenarios
←   The ERC-721 NFT standardReentrancy attacks   →