Web3 / Smart Contract Security Intro

Reentrancy, access control bugs, integer overflow/underflow, and oracle manipulation — why immutable, financially-loaded smart contract bugs are uniquely unforgiving.

expert 70m 3 tasks

Learning Objectives

  • Explain why smart contract bugs are uniquely severe: immutability and direct financial value
  • Explain the reentrancy attack pattern and the checks-effects-interactions fix
  • Identify access control vulnerabilities in smart contracts
  • Explain oracle manipulation and front-running/MEV as DeFi-specific attack classes
  • Describe integer overflow/underflow risk in smart contract arithmetic

Why Smart Contract Bugs Are Uniquely Severe

A traditional web application bug can usually be patched and deployed within minutes. A deployed smart contract is, by design, immutable — once live on the blockchain, its code typically cannot be changed. Combined with the fact that contracts frequently hold real financial value directly (unlike a typical web app, which holds data about value stored elsewhere), a single bug can result in an instant, irreversible, and often fully public loss of funds.

Reentrancy: The Classic Smart Contract Vulnerability

Reentrancy exploits a contract that makes an external call (e.g. sending funds) before updating its own internal state:

// VULNERABLE
function withdraw(uint amount) public {
    require(balances[msg.sender] >= amount);
    (bool success, ) = msg.sender.call{value: amount}("");  // external call FIRST
    balances[msg.sender] -= amount;                          // state update AFTER
}

A malicious contract's fallback function can call withdraw() again during the external call, before balances[msg.sender] is decremented — repeating the withdrawal multiple times against the same original balance check. This is exactly the pattern behind the 2016 DAO hack.

The fix — checks-effects-interactions: update internal state before making any external call:

// FIXED
function withdraw(uint amount) public {
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount;                          // effects FIRST
    (bool success, ) = msg.sender.call{value: amount}("");    // interaction AFTER
}

Access Control Vulnerabilities

A missing or incorrect access modifier on a sensitive function (e.g. one that mints tokens or withdraws contract funds) lets any address call it, not just the intended owner/admin. This is functionally identical to a missing authorization check on a web API endpoint — the same web security concept applied to on-chain code.

Integer Overflow/Underflow

Older Solidity versions (pre-0.8) don't automatically revert on arithmetic overflow/underflow — a uint decremented below zero silently wraps around to a massive number instead of erroring, which can be weaponized to bypass balance checks entirely. Modern Solidity (0.8+) reverts by default, but contracts using unchecked blocks or older compiler versions remain vulnerable.

Oracle Manipulation and Front-Running/MEV

  • Oracle manipulation — many DeFi contracts rely on an external price oracle; if that oracle can be manipulated (e.g. via a flash loan distorting a price briefly), a contract trusting it can be tricked into believing an asset is worth far more or less than its real value
  • Front-running/MEV (Maximal Extractable Value) — because pending blockchain transactions are visible before confirmation, an attacker (or the block producer itself) can observe a profitable pending transaction and insert their own transaction ahead of it to profit from the resulting price movement

Common Pitfalls

  • Deploying a contract holding real value without an independent security audit, given that bugs are effectively permanent once live
  • Trusting a single price oracle with no manipulation resistance (e.g. time-weighted averaging, multiple sources)
  • Assuming Solidity 0.8+'s default overflow checks make all arithmetic automatically safe, ignoring unchecked blocks
  • Treating smart contract security as identical to web security without accounting for immutability and direct financial stakes

Unlike a typical web app, a live contract usually cannot simply be patched after a bug is discovered.

✦ Answer the questions to complete this task

Why does a smart contract bug tend to be more severe than an equivalent traditional web app bug?

The vulnerable version sends funds out before recording that the balance was already spent.

✦ Answer the questions to complete this task

In the vulnerable withdraw() pattern, what is the ordering mistake that enables reentrancy?

The external call — the riskiest part — should always be the very last thing a function does.

✦ Answer the questions to complete this task

What does the checks-effects-interactions pattern require, in order?

💪 Exercises & Challenges

📝 MCQ expert +20 XP

Web3 / Smart Contract Security Intro MCQ

Test your understanding of Web3 / Smart Contract Security Intro.

Start →
⚙️ Practical expert +35 XP

Rewrite a Vulnerable Withdraw Function

Given the vulnerable withdraw() function shown in the lesson content (external call before balance update), rewrite it applying the checks-effects-interactions pattern, and explain in one sentence why

Start →
🚩 Challenge expert +55 XP

Identify the Oracle Attack

A DeFi lending protocol's post-mortem reveals: an attacker took out a large flash loan, used it to briefly distort the price reported by the protocol's single price oracle, borrowed against collateral

Start →