# Smart Contract Vulnerability Types: A Reference Guide for Web3 Teams

> A clear reference of smart contract vulnerability types — from reentrancy to oracle manipulation — with how each works and how it is prevented. Built for Web3 teams.

- **Published:** 2026-06-19
- **Author:** Clixo
- **Reading time:** 6 min read
- **Tags:** smart-contract-vulnerabilities, web3-security, solidity, defi
- **Canonical URL:** https://clixo.sh/blog/smart-contract-vulnerability-types-reference

Understanding the specific categories of smart contract vulnerabilities is the prerequisite for preventing them, auditing for them, and evaluating audit reports that reference them. This reference covers the vulnerability classes that appear most frequently in production exploits, organized by category.

```mermaid
flowchart TD
  A[Smart Contract Vulnerabilities] --> B[Execution Flow]
  A --> C[Arithmetic]
  A --> D[Access Control]
  A --> E["Oracle & Price"]
  A --> F["Logic & Design"]
  A --> G[Upgradeability]
  B --> B1["Reentrancy / DoS"]
  C --> C1["Overflow / Precision Loss"]
  D --> D1["Missing Guards / Unsafe Transfer"]
  E --> E1["Spot Price / Stale Data"]
  F --> F1["Front-Running / Replay"]
  G --> G1["Storage Collision / delegatecall"]
```

## Execution Flow Vulnerabilities

### Reentrancy

A reentrancy attack occurs when an external call — most commonly an ETH transfer — triggers code in a recipient contract before the calling contract has finished updating its state. The recipient calls back into the original contract, finding state that still reflects the pre-call values, and exploits the discrepancy.

**Prevention**: Checks-Effects-Interactions (CEI) pattern — update all state before making external calls. Apply `nonReentrant` guards from OpenZeppelin's `ReentrancyGuard` on all value-transferring functions.

### Denial of Service (DoS)

Several patterns cause smart contract functions to become permanently uncallable:

- A loop that iterates over an unbounded array — the gas cost eventually exceeds the block limit
- A function that depends on a `push` transfer to a list of recipients — if any recipient reverts, the entire call fails
- A function that requires an external call to succeed — if that external protocol is bricked or the call is blocked, the function is stuck

**Prevention**: Design for pull rather than push payments. Bound loops or paginate them. Avoid single points of external dependency in critical paths.

## Arithmetic Vulnerabilities

### Integer Overflow and Underflow

Before Solidity 0.8, arithmetic operations could silently wrap around — adding 1 to the maximum `uint256` value produced 0. After 0.8, arithmetic reverts on overflow by default. The remaining risk is in explicit `unchecked` blocks, where arithmetic checks are disabled for gas savings.

**Prevention**: Keep `unchecked` blocks narrow and only around arithmetic that is demonstrably safe. Review every `unchecked` block in an audit.

### Truncation via Type Casting

Casting a larger integer type to a smaller one silently discards the high bits. A `uint256` value of 300 cast to `uint8` produces 44, not 300, with no revert.

**Prevention**: Use OpenZeppelin's `SafeCast` library for all downcast operations where the value's range is not provably within bounds.

### Precision Loss and Rounding

Integer division in Solidity truncates toward zero. Division before multiplication in a compound expression loses precision. In protocols where rounding direction is economically significant — fee calculations, reward distributions — accumulated rounding errors can be exploited.

**Prevention**: Multiply before dividing. Document intended rounding direction. For protocols where precision matters at scale, use fixed-point libraries.

## Access Control Vulnerabilities

### Missing Function Guards

A function that modifies sensitive state or transfers value with no access control is callable by anyone. This is one of the most frequently exploited classes in DeFi — consistently appearing in exploit post-mortems.

**Prevention**: Every privileged function must have an enforcing modifier. Maintain an explicit list of all restricted functions and their guards.

### Unprotected Initializers

Upgradeable contracts use an `initialize` function instead of a constructor. Without the `initializer` modifier and `_disableInitializers()` in the implementation constructor, anyone can reinitialize the contract and take ownership.

**Prevention**: Use OpenZeppelin's `Initializable`. Always call `_disableInitializers()` in implementation constructors.

### Unsafe Privilege Transfer

Single-step ownership transfer allows transferring control to an address without confirming that address can accept it. Sending ownership to a wrong address or a contract that cannot call `acceptOwnership` permanently bricks admin access.

**Prevention**: Use `Ownable2Step` for all ownership transfers.

## Oracle and Price Vulnerabilities

### Spot Price Manipulation

Protocols that read a DEX spot price within a transaction to determine exchange rates or collateral values can have that price manipulated within the same transaction via flash loans. An attacker borrows large amounts, moves the spot price, exploits the protocol, and repays — all in one transaction.

**Prevention**: Use time-weighted average prices (TWAPs) for longer windows of protection, or use aggregated off-chain oracle feeds like Chainlink. Understand the specific trade-offs of each.

### Stale Oracle Data

Oracle price feeds can fail to update during periods of network congestion or oracle node issues. A protocol that consumes a stale price without checking the last-updated timestamp may liquidate positions incorrectly or accept undercollateralized positions.

**Prevention**: Check oracle heartbeat and last-update timestamps. Have a defined behavior for when the oracle is stale — typically a circuit breaker or pause.

## Logic and Design Vulnerabilities

### Front-Running

Transactions on public blockchains are visible in the mempool before they are included in a block. Attackers — or searchers running MEV bots — can observe pending transactions and submit their own transactions with higher gas fees to be processed first, extracting value.

This affects protocols with predictable economic outcomes: batch auctions, NFT mints with uniform pricing, DEX trades with large slippage.

**Prevention**: Commit-reveal schemes, slippage parameters on trades, batch settlement with uniform clearing prices, or relying on private mempools where applicable.

### tx.origin Authorization

Using `tx.origin` for authorization checks whether the original signer of a transaction is a specific address, but it does not verify the immediate caller. A phishing contract can initiate a transaction through a victim's account and pass a `tx.origin` check.

**Prevention**: Always use `msg.sender` for authorization. `tx.origin` is only appropriate for specific, narrow use cases, never as a primary authorization check.

### Signature Replay

If a contract accepts signed messages as authorization, those signatures can be replayed — used again in a different context or on a different chain — unless the signing scheme includes a nonce, contract address, and chain ID in the signed payload.

**Prevention**: Follow EIP-712 for structured data signing. Include `chainId`, contract address, a nonce, and a message expiry in every signed payload. Validate and increment nonces on use.

## Upgradeability Vulnerabilities

### Storage Collision

Upgradeable proxy contracts separate storage (in the proxy) from logic (in the implementation). If a new implementation version introduces a storage variable at a slot already used by the proxy itself, reading or writing that variable corrupts the proxy's own state — including the address of the implementation.

**Prevention**: Use OpenZeppelin's `Upgradeable` contracts and storage gap patterns. Append-only storage in upgrade paths. Run storage layout checks between implementation versions.

### Delegatecall to Untrusted Contracts

`delegatecall` executes code from another contract in the context of the calling contract — using the calling contract's storage. A `delegatecall` to a malicious or compromised contract gives it full read and write access to the calling contract's state.

**Prevention**: Only `delegatecall` contracts you control and have reviewed. Never `delegatecall` to user-supplied addresses.

---

This list covers the most common classes, not every possible vulnerability. Auditors work against a more expansive mental model developed through reviewing dozens or hundreds of contracts. Using this reference for code review and test case development is useful; it does not substitute for an expert review.

Clixo engineers build Web3 protocols with these patterns in mind from the first line of code. For protocol teams that want a build partner who knows what auditors look for, [reach out](https://clixo.sh/#contact).

---

Clixo · 1141 W Bryn Mawr Ave, Itasca, IL 60143, US · [hello@clixo.sh](mailto:hello@clixo.sh)
[Start a build](https://clixo.sh/#contact) · [All services](https://clixo.sh/services) · [Agent guide (llms.txt)](https://clixo.sh/llms.txt)
