> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/web3pentesting/web3-attack-topic-cheatsheet.md).

# Web3 Attack Topic Cheatsheet

This is the full list of attack categories you'll work through after the basics. Each one includes: what it is, why it happens, a simplified code pattern showing the flaw, how an attacker actually exploits it, and how it's fixed. This is defensive/educational material - the goal is recognizing and preventing these patterns, not attacking live systems.

***

### Table of Contents

**Part A - Smart Contract Level Attacks**

1. Reentrancy
2. Integer Overflow and Underflow
3. Access Control Flaws
4. Unchecked External Calls
5. Denial of Service (DoS)
6. Front-Running and MEV
7. Timestamp Dependence
8. Weak Randomness
9. Delegatecall Injection
10. Signature Replay Attacks
11. Flash Loan Attacks
12. Oracle Manipulation
13. Logic and Business-Rule Errors
14. Self-Destruct Abuse
15. Governance Attacks

**Part B - Broader Web3 System Attacks** 16. Wallet and Key Management Attacks 17. Phishing and Social Engineering 18. RPC and Node-Level Attacks 19. Bridge Exploits 20. Frontend and Supply Chain Attacks

**Part C - Wrap-Up** 21. Severity Framework 22. Recap Table

***

## Part A - Smart Contract Level Attacks

### 1. Reentrancy

#### What it is

A contract calls out to an external address (sending it ETH or calling one of its functions) before it finishes updating its own internal state. If that external address is itself a contract, it can use that window to call back into the original function again, repeating the action before the first call ever finished.

#### Why it happens

Developers write logic in a natural order: check a condition, send funds, then update the balance. But sending funds can hand control to another contract, and that contract can call back in before the balance update ever runs.

```
              THE VULNERABLE PATTERN (simplified)

  function withdraw(uint amount) external {
      require(balances[msg.sender] >= amount);   // 1. check
      (bool sent, ) = msg.sender.call{value: amount}("");  // 2. send funds
      require(sent);
      balances[msg.sender] -= amount;             // 3. update state (TOO LATE)
  }
```

```
                    THE ATTACK SEQUENCE

  Attacker contract calls withdraw()
          |
          v
  Step 1: check passes (balance is still 100)
          |
          v
  Step 2: funds are sent to the attacker's contract
          |
          v
  The attacker's contract has a receive() function that
  immediately calls withdraw() AGAIN, before step 3 ever runs
          |
          v
  Step 1 check passes AGAIN (balance still shows 100,
  since it was never decremented)
          |
          v
  This repeats until the contract is drained
```

#### The fix

Follow the checks-effects-interactions pattern: do all your checks first, then update all state, and only then make any external call.

```
              THE FIXED PATTERN

  function withdraw(uint amount) external {
      require(balances[msg.sender] >= amount);   // 1. check
      balances[msg.sender] -= amount;             // 2. update state FIRST
      (bool sent, ) = msg.sender.call{value: amount}("");  // 3. interact LAST
      require(sent);
  }
```

Reentrancy guards (like OpenZeppelin's `nonReentrant` modifier) are also commonly used as a second layer of defense, blocking a function from being re-entered while it's still executing.

***

### 2. Integer Overflow and Underflow

#### What it is

Numbers in Solidity are stored in fixed-size types (like `uint256`). Overflow happens when a number goes above the maximum the type can hold and wraps back around to zero (or a small number). Underflow is the same idea in reverse - subtracting past zero wraps around to a huge number.

#### Why it happens

In Solidity versions before 0.8, arithmetic did not automatically check for this, so a subtraction like `balance - amount` where `amount` is larger than `balance` would silently produce an enormous number instead of failing.

```
                    UNDERFLOW EXAMPLE (pre-0.8 Solidity)

  uint256 balance = 5;
  balance = balance - 10;

  Expected: an error, since you can't go below zero
  Actual (pre-0.8): balance wraps around to a massive number
                     close to the maximum value a uint256 can hold
```

An attacker with a small starting balance could trigger an underflow to suddenly appear to have an almost unlimited balance.

#### The fix

Solidity 0.8 and later automatically reverts on overflow/underflow by default, which eliminated most of this bug class. For older code, or code that intentionally uses `unchecked` blocks for gas savings, using a library like OpenZeppelin's SafeMath (or being extremely careful with any `unchecked` block) is the mitigation.

***

### 3. Access Control Flaws

#### What it is

A function that should only be callable by a specific address (like the contract's owner or an admin) is missing that restriction, or has it implemented incorrectly.

#### Common variations

* A sensitive function (like withdrawing funds or changing ownership) has no restriction at all.
* The restriction check uses the wrong comparison (e.g. checking `tx.origin` instead of `msg.sender`, which can be tricked through an intermediate contract).
* A function meant to be `internal` is accidentally marked `public` or `external`.
* Initialization functions (common in upgradeable contracts) can be called more than once, or called by anyone, letting an attacker take ownership during or after deployment.

```
                    ACCESS CONTROL EXAMPLE

  BAD: no restriction at all
  function setOwner(address newOwner) external {
      owner = newOwner;   // anyone can call this and take over!
  }

  GOOD: properly restricted
  function setOwner(address newOwner) external onlyOwner {
      owner = newOwner;
  }
```

#### The fix

Use a well-tested access control pattern (like OpenZeppelin's `Ownable` or role-based `AccessControl`), double-check every state-changing function has the correct modifier, and be careful with `tx.origin` (generally avoid using it for authentication entirely, since `msg.sender` is the correct and safer choice in almost all cases).

***

### 4. Unchecked External Calls

#### What it is

When a contract calls another contract or sends ETH, that call can fail. If the calling contract doesn't check whether the call succeeded, it may continue executing as if everything worked, even though it didn't.

```
                    UNCHECKED CALL EXAMPLE

  BAD:
  recipient.call{value: amount}("");
  // no check on whether this succeeded - execution continues regardless

  GOOD:
  (bool sent, ) = recipient.call{value: amount}("");
  require(sent, "transfer failed");
```

#### Why it matters

This can lead to a contract believing funds were sent when they weren't, breaking internal accounting, or letting a malicious recipient deliberately cause a call to fail as part of a larger attack (sometimes combined with denial-of-service patterns below).

***

### 5. Denial of Service (DoS)

#### What it is

An attacker makes a contract function too expensive, or outright impossible, to execute - blocking legitimate users from using it.

#### Common patterns

* **Unbounded loops** - a function loops over an array that can grow indefinitely (e.g. a list of all depositors). As the array grows, the function eventually costs more gas than the block gas limit allows, making it permanently uncallable.
* **Failed external call blocking logic** - if a contract's logic depends on successfully sending funds to a specific address before continuing (e.g. paying out the previous highest bidder before accepting a new bid), an attacker can deploy a contract that deliberately rejects the payment, freezing the entire function for everyone.

```
                    DOS VIA UNBOUNDED LOOP

  function payAllInvestors() external {
      for (uint i = 0; i < investors.length; i++) {
          investors[i].transfer(payout);
      }
  }

  As `investors` grows over time, this loop eventually
  costs more gas than a single block allows -> the
  function becomes permanently uncallable for everyone,
  not just the attacker.
```

#### The fix

Avoid loops over data structures that can grow without bound, especially ones influenced by user input. Use "pull" patterns instead of "push" patterns - let each user withdraw their own funds individually, rather than the contract trying to push funds out to everyone in one transaction.

***

### 6. Front-Running and MEV

#### What it is

Because pending transactions are visible in the public mempool before they're confirmed, anyone watching can see a profitable transaction coming and submit their own transaction with a higher gas fee to get it processed first. This broader category is often called MEV (Maximal Extractable Value).

#### Common patterns

* **Sandwich attacks** - on a decentralized exchange, an attacker sees a large pending buy order, buys first to push the price up, lets the victim's trade execute at the worse price, then immediately sells for a profit.
* **Front-running a profitable discovery** - if a contract rewards whoever finds the solution to a puzzle or claims a specific resource first, an attacker can watch the mempool, copy the winning transaction's data, and resubmit it with higher gas to win instead.

```
              SANDWICH ATTACK SEQUENCE

  1. Attacker sees victim's large "buy Token X" transaction
     sitting in the mempool, not yet confirmed

  2. Attacker submits their OWN buy order with a higher gas
     fee, so it gets processed FIRST -> price of Token X rises

  3. Victim's original transaction executes at this now
     worse price

  4. Attacker immediately sells Token X at the new,
     inflated price for a profit
```

#### The fix

Techniques include commit-reveal schemes (hiding the actual transaction details until a later step), using private transaction relays that don't expose pending transactions publicly, and setting tight slippage tolerances on trades so a sandwich attack becomes unprofitable or fails outright.

***

### 7. Timestamp Dependence

#### What it is

Contract logic that relies on `block.timestamp` for anything security-critical, such as randomness or precise timing, can be manipulated - validators have some (limited) ability to influence the timestamp of a block they produce.

```
              WEAK PATTERN

  function play() external {
      if (block.timestamp % 2 == 0) {
          payout();  // relying on timestamp parity as "randomness"
      }
  }
```

A validator producing the block could nudge the timestamp within their allowed tolerance to influence the outcome in their favor.

#### The fix

Never use `block.timestamp` as a source of randomness or for extremely tight time-sensitive logic. It's fine for coarse checks (like "has at least a day passed"), but not for anything an attacker could meaningfully profit from manipulating within a small window.

***

### 8. Weak Randomness

#### What it is

True randomness is difficult to generate on a deterministic, fully public blockchain, since every node needs to independently compute the same result. Naive approaches (using `block.timestamp`, `block.difficulty`, or `blockhash`) are all publicly known or predictable values, which means an attacker can predict or even influence the "random" outcome.

```
              WEAK PATTERN

  uint random = uint(keccak256(abi.encodePacked(
      block.timestamp, block.difficulty, msg.sender
  ))) % 100;

  Every one of these inputs is either publicly visible
  before the transaction confirms, or influenceable by
  whoever is producing the block.
```

#### The fix

Use a dedicated verifiable randomness solution (an oracle-based randomness service is the standard industry approach), which provides randomness that can be cryptographically proven to be fair and wasn't known in advance.

***

### 9. Delegatecall Injection

#### What it is

`delegatecall` lets a contract execute code from another contract's address, but using the calling contract's own storage. If used carelessly, an attacker can trick a contract into delegatecalling into malicious code that overwrites the calling contract's storage in unexpected ways - including things like the contract's owner variable.

```
              THE DANGER OF DELEGATECALL

  Normal call: Contract A calls Contract B
               B's code runs using B's OWN storage

  Delegatecall: Contract A delegatecalls Contract B
                B's code runs but using A's storage instead

  If an attacker controls what code runs at the delegatecall
  target, they can write arbitrary values into Contract A's
  storage slots - including slot 0, which is often where the
  owner address or other critical state lives.
```

This pattern was central to a well-known real-world multisig wallet hack, where a library contract's initialization function was left callable by anyone, and a delegatecall-based structure let an attacker eventually become the owner and later trigger a self-destruct that froze a large amount of funds.

#### The fix

Be extremely cautious with delegatecall, only use it with fully trusted, immutable target contracts, and ensure storage layouts between the calling contract and the target are carefully matched and controlled (this is also the mechanism behind proxy/upgradeable contract patterns, which need very careful storage layout management for exactly this reason).

***

### 10. Signature Replay Attacks

#### What it is

Many contracts accept signed messages off-chain (for example, a user signs a message authorizing a specific action, and the contract verifies that signature on-chain). If the contract doesn't include something unique to prevent reuse, an attacker can resubmit ("replay") a previously valid signature to trigger the action again.

```
              REPLAY ATTACK SEQUENCE

  1. User signs a message: "transfer 10 tokens to Bob"
  2. Contract verifies the signature and executes it
  3. Attacker captures that same signed message
  4. Attacker resubmits the EXACT same signature later
  5. If nothing prevents reuse, the contract executes the
     same transfer again, and again, and again
```

Replay can also happen across different chains - a signature valid on one network being reused on another network running the same contract code, if the signed message doesn't specify which chain it belongs to.

#### The fix

Include a nonce (a number that increases with each use and is checked/updated on-chain) so each signature can only be used once, and include the chain ID in the signed message to prevent cross-chain replay.

***

### 11. Flash Loan Attacks

#### What it is

A flash loan lets someone borrow a very large amount of funds with no collateral, as long as it's borrowed and repaid within a single transaction. This is a legitimate DeFi feature, but attackers use flash loans to temporarily gain enormous capital, manipulate a protocol's state (often prices, explained more below), profit from that manipulation, repay the loan, and keep the profit - all within one transaction, meaning it requires no real capital of their own.

```
              A TYPICAL FLASH LOAN ATTACK SHAPE

  1. Borrow a huge sum via flash loan (no collateral needed)
          |
          v
  2. Use that huge sum to manipulate something (often a
     price feed on a low-liquidity exchange)
          |
          v
  3. Interact with a target protocol that trusted the
     now-manipulated data, profiting from the distortion
          |
          v
  4. Repay the flash loan (required within the same
     transaction, or the entire transaction reverts)
          |
          v
  5. Keep the leftover profit
```

#### The fix

This isn't really a single "bug" to patch - it's a design consideration. Protocols need to ensure their logic can't be meaningfully manipulated within a single transaction, especially around pricing (see Oracle Manipulation below), and should be resistant to any single actor temporarily controlling a large share of available liquidity.

***

### 12. Oracle Manipulation

#### What it is

Smart contracts often need real-world data they can't generate themselves, like the current price of an asset. This data comes from an "oracle." If a contract trusts a manipulable price source, an attacker can distort that price temporarily (often combined with a flash loan) to trick the contract into miscalculating something in the attacker's favor.

```
              PRICE ORACLE MANIPULATION EXAMPLE

  A lending protocol checks a token's price by looking
  directly at a single, low-liquidity decentralized
  exchange pool.

  1. Attacker takes a flash loan
  2. Attacker dumps a huge amount of Token X into that
     single pool, crashing its price within the pool
  3. Attacker uses Token X as collateral, and the lending
     protocol - trusting that now-crashed price - lets them
     borrow far more than Token X is actually worth
  4. Attacker walks away with the borrowed funds, price
     recovers after the attacker's transaction ends
```

#### The fix

Use decentralized, manipulation-resistant oracle networks that aggregate data from many independent sources rather than trusting a single on-chain pool, and consider using time-weighted average prices (TWAP) instead of the current instantaneous price, since averaging over time makes momentary manipulation far less effective.

***

### 13. Logic and Business-Rule Errors

#### What it is

Not every vulnerability fits a named pattern. Sometimes a contract is technically "safe" from reentrancy, overflow, and access control issues, but the actual business logic itself is simply wrong - a math formula is inverted, a rounding error consistently favors one side, a condition uses the wrong comparison operator, or a specific edge case (like an amount of exactly zero) wasn't considered.

#### Why this category matters

This is often the hardest category to catch with automated tools, since nothing about the code is syntactically dangerous - it just doesn't do what the protocol actually intended. This is where deep manual review and a real understanding of the protocol's intended behavior becomes essential, and it's a large part of why experienced human auditors remain necessary even as automated tools improve.

***

### 14. Self-Destruct Abuse

#### What it is

The `selfdestruct` operation removes a contract's code and forcibly sends its remaining ETH balance to a specified address - and critically, this forced ETH transfer does not trigger the receiving contract's normal receive/fallback logic, and cannot be blocked or rejected by the recipient.

#### Why this matters

Contracts that rely on assumptions like "this contract's ETH balance can only change through my own defined functions" can be broken, since `selfdestruct` can forcibly inject ETH into a contract from outside its normal logic entirely, potentially throwing off internal accounting that assumed a controlled, predictable balance.

#### The fix

Never assume a contract's actual ETH balance (checked via `address(this).balance`) will exactly match your internally tracked accounting variables - track balances internally and don't rely on the raw contract balance for critical logic.

***

### 15. Governance Attacks

#### What it is

Many protocols are controlled by a decentralized governance system, where token holders vote on proposals. If an attacker can (even temporarily) acquire enough voting power, they can pass a malicious proposal - for example, one that drains the protocol's treasury or changes critical parameters in their favor.

#### Common patterns

* **Flash loan governance attacks** - borrowing a massive amount of governance tokens right before a vote snapshot, voting maliciously, then returning the tokens, if the protocol doesn't guard against this.
* **Low voter turnout exploitation** - if genuine participation in governance is low, a smaller amount of capital than expected may be enough to pass a harmful proposal.

#### The fix

Common mitigations include requiring tokens to be locked for a period before they count toward voting power (preventing flash-loan-style borrowing right before a vote), timelocks on executing passed proposals (giving the community time to react to a malicious one), and snapshot-based voting power calculated well before the vote, rather than at the moment of the vote itself.

***

## Part B - Broader Web3 System Attacks

These move beyond the smart contract itself, into the rest of the system a real Web3 pentest has to cover.

### 16. Wallet and Key Management Attacks

Private keys are the single point of failure for an account. Attacks in this category include insecure key storage, weak or predictable seed phrase generation, malicious or compromised wallet browser extensions, and clipboard-hijacking malware that silently swaps a copied wallet address for the attacker's own right before a user pastes it into a transaction.

### 17. Phishing and Social Engineering

A huge share of real-world Web3 losses come from tricking users directly rather than breaking code. This includes fake dapp websites that closely mimic a real protocol's interface, malicious transaction approval requests disguised as something harmless (like an NFT mint), and fraudulent "support" accounts on social platforms that trick users into revealing seed phrases or approving malicious contract permissions.

### 18. RPC and Node-Level Attacks

Since most dapps connect through a third-party RPC provider rather than running their own node, a compromised or malicious RPC endpoint could theoretically feed a dapp false blockchain data, or log and expose sensitive information about a user's activity. Running or verifying against your own node is one mitigation for high-security use cases.

### 19. Bridge Exploits

Bridges let assets move between different blockchains, and they are historically one of the highest-value attack targets in the entire Web3 space, since they often hold enormous amounts of locked value and rely on complex trust assumptions (validators, multisigs, or custom consensus mechanisms) that are harder to reason about than a single-chain smart contract. Common bridge vulnerabilities include compromised validator keys, flawed signature verification logic, and mismatched assumptions between the two chains being bridged.

### 20. Frontend and Supply Chain Attacks

Even a perfectly secure smart contract can be undermined if the website users interact with is compromised - for example, through a hacked DNS record redirecting users to a fake site, a compromised third-party JavaScript library silently altering transaction data before the user signs it, or a compromised developer's deployment pipeline pushing malicious frontend code. This is why frontend security and dependency/supply-chain review are part of a comprehensive Web3 pentest, not just the on-chain contract review.

***

## Part C - Wrap-Up

### 21. Severity Framework

When you find any of the above in a real assessment, it needs to be ranked, not just described. A common approach:

| Severity      | Rough definition                                                                                            |
| ------------- | ----------------------------------------------------------------------------------------------------------- |
| Critical      | Direct, reliable loss of user or protocol funds, or full compromise of core functionality                   |
| High          | Significant impact, but requires specific conditions or is more complex to trigger                          |
| Medium        | Real impact, but limited in scope, requires unusual conditions, or has partial mitigations already in place |
| Low           | Minor issue, best-practice violation, or something exploitable only in edge cases with minimal impact       |
| Informational | Not a vulnerability itself, but worth noting for code quality, gas efficiency, or future risk               |

### 22. Recap Table

| #  | Attack                      | One-line summary                                                             |
| -- | --------------------------- | ---------------------------------------------------------------------------- |
| 1  | Reentrancy                  | External call happens before state update, allowing repeated re-entry        |
| 2  | Integer overflow/underflow  | Arithmetic wraps around type limits unexpectedly                             |
| 3  | Access control flaws        | Missing or incorrect restriction on sensitive functions                      |
| 4  | Unchecked external calls    | Failure of a call isn't checked, execution continues incorrectly             |
| 5  | Denial of service           | A function becomes too expensive or impossible to call                       |
| 6  | Front-running/MEV           | Visible pending transactions get exploited by faster/higher-fee transactions |
| 7  | Timestamp dependence        | Security-critical logic relies on a manipulable block timestamp              |
| 8  | Weak randomness             | "Random" values are actually predictable or influenceable                    |
| 9  | Delegatecall injection      | Executing untrusted code that can corrupt the caller's own storage           |
| 10 | Signature replay            | A valid signature is reused without a nonce/chain ID to prevent it           |
| 11 | Flash loan attacks          | Huge temporary capital used to manipulate state within one transaction       |
| 12 | Oracle manipulation         | Trusting a manipulable price/data source                                     |
| 13 | Logic/business-rule errors  | The code is "safe" but doesn't do what was actually intended                 |
| 14 | Self-destruct abuse         | Forced ETH injection breaks a contract's internal accounting assumptions     |
| 15 | Governance attacks          | Acquiring enough voting power to pass a malicious proposal                   |
| 16 | Wallet/key attacks          | Compromising the private key or seed phrase itself                           |
| 17 | Phishing/social engineering | Tricking the user directly instead of breaking code                          |
| 18 | RPC/node attacks            | Compromising or spoofing the connection between a dapp and the blockchain    |
| 19 | Bridge exploits             | Attacking the cross-chain trust mechanism                                    |
| 20 | Frontend/supply chain       | Compromising the website or dependencies users actually interact with        |

#### The one thing to remember

Every attack on this sheet ultimately comes from the same root cause in some form: a piece of code or a system trusted something it shouldn't have - user input, an external call's outcome, a timestamp, a price feed, a signature, or a dependency - without verifying it was safe to trust. Learning to ask "what is this trusting, and could that trust be broken" is the actual skill underneath every entry on this list.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/web3pentesting/web3-attack-topic-cheatsheet.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
