# Dos Attack

> Auto-loaded by logic-auditor agent during Phase 2. Provides detection patterns for: gas griefing, unbounded loops, external call failures, block gas limit exploitation, storage DoS, and liveness failures. Core artifact: Liveness Analysis Map.

- Skill: `purpleailab/dos-attack` (Agent Skill)
- Install (CLI): `npx skillmds@latest add purpleailab/dos-attack`
- Raw SKILL.md: https://api.skillmd.com/api/skills/purpleailab/dos-attack/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: purpleailab (https://skillmd.com/u/purpleailab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/purpleailab/dos-attack

---


# Denial of Service (DoS) Attack Patterns

**OWASP SC10:2025** - DoS attacks prevent legitimate users from accessing protocol functionality, potentially locking funds permanently.

**2025-2026 Statistics**: DoS vulnerabilities caused protocol freezes affecting $180M+ in locked funds, with gas griefing attacks increasing 45% YoY.

---

## Why DoS Happens (Root Causes)

### Root Cause 1: Unbounded Iteration

Loops without gas limits become unusable as data grows.

```solidity
// VULNERABLE: Unbounded loop
function distributeRewards() external {
    for (uint256 i = 0; i < holders.length; i++) {  // @audit holders can grow unbounded
        token.transfer(holders[i], rewards[holders[i]]);
    }
}
```

**Attacker's view**: "I'll create thousands of tiny positions. Eventually, no one can call this function."

### Root Cause 2: External Call Dependency

Function success depends on external call that attacker can make fail.

```solidity
// VULNERABLE: Relies on external transfer success
function withdrawAll() external {
    for (uint256 i = 0; i < users.length; i++) {
        payable(users[i]).transfer(balances[users[i]]);  // @audit One revert blocks all
    }
}
```

**Attacker's view**: "If I'm in the array and my receive() reverts, nobody gets paid."

### Root Cause 3: Storage Slot Exhaustion

Unlimited storage growth makes operations cost-prohibitive.

```solidity
// VULNERABLE: Unlimited storage growth
mapping(address => uint256[]) public userDeposits;

function deposit() external payable {
    userDeposits[msg.sender].push(msg.value);  // @audit Array grows forever
}

function getTotalDeposits(address user) external view returns (uint256) {
    uint256 total;
    for (uint256 i = 0; i < userDeposits[user].length; i++) {  // @audit View can run out of gas
        total += userDeposits[user][i];
    }
    return total;
}
```

### Root Cause 4: Block Gas Limit Exploitation

Transaction exceeds block gas limit, making it impossible to execute.

```solidity
// VULNERABLE: Can exceed block gas limit
function processAllPending() external {
    while (pendingQueue.length > 0) {
        _processSingle(pendingQueue[0]);
        pendingQueue.pop();
    }
}
```

---

## The Liveness Analysis Map (Core Artifact)

For each critical function, document:

```
Function: withdrawAll()
├── External Calls: N calls to user addresses
├── Loop Bound: users.length (unbounded)
├── Gas Estimate: O(n) where n = users count
├── Failure Mode: Single revert blocks all withdrawals
├── Recovery: None - funds permanently locked
└── Risk: CRITICAL
```

| Function | Dependency | Bound | Failure Impact | Recovery |
|----------|------------|-------|----------------|----------|
| distributeRewards | N transfers | Unbounded | Protocol freeze | None |
| processQueue | Queue size | Bounded (100) | Temporary delay | Retry |
| batchLiquidate | M liquidations | User-controlled | Partial failure | Continue |

---

## Detection Patterns

### Pattern 1: Unbounded Loop DoS

**Root Cause**: Unbounded Iteration

```solidity
// VULNERABLE: Loop over dynamic array
function processAll() external {
    for (uint256 i = 0; i < items.length; i++) {
        _process(items[i]);
    }
}
```

**Attack Flow**:
1. Attacker adds many small items to array
2. Array grows to thousands of entries
3. Gas cost exceeds block limit
4. Function becomes uncallable
5. Funds/operations permanently stuck

**Search Queries**:
```
Grep("for.*\\.length|while.*\\.length", glob="**/*.sol")
Grep("for.*i\\+\\+|for.*i < ", glob="**/*.sol")
```

**Mitigation**:
```solidity
// SECURE: Pagination pattern
function processRange(uint256 start, uint256 end) external {
    require(end <= items.length && end - start <= MAX_BATCH);
    for (uint256 i = start; i < end; i++) {
        _process(items[i]);
    }
}
```

### Pattern 2: External Call Failure DoS

**Root Cause**: External Call Dependency

```solidity
// VULNERABLE: One failure blocks all
function refundAll() external {
    for (uint256 i = 0; i < refundees.length; i++) {
        (bool success,) = refundees[i].call{value: amounts[i]}("");
        require(success, "Refund failed");  // @audit Blocks on any failure
    }
}
```

**Attack Flow**:
1. Attacker enters system with contract that reverts on receive
2. Refund function iterates to attacker's address
3. Attacker's receive() reverts
4. Entire function reverts
5. All refunds blocked

**Search Queries**:
```
Grep("\\.call\\{value.*require\\(success", glob="**/*.sol")
Grep("\\.transfer\\(|send\\(", glob="**/*.sol")
```

**Mitigation**:
```solidity
// SECURE: Pull pattern
mapping(address => uint256) public pendingRefunds;

function withdraw() external {
    uint256 amount = pendingRefunds[msg.sender];
    pendingRefunds[msg.sender] = 0;
    (bool success,) = msg.sender.call{value: amount}("");
    require(success);
}
```

### Pattern 3: Gas Griefing

**Root Cause**: Unchecked Gas Forwarding

```solidity
// VULNERABLE: Forwards all gas to untrusted call
function executeCallback(address target, bytes calldata data) external {
    (bool success,) = target.call(data);  // @audit Attacker can consume all gas
    require(success);
}
```

**Attack Flow**:
1. Attacker creates contract with expensive fallback
2. Callback executes, consuming all forwarded gas
3. Parent transaction fails or behaves unexpectedly
4. Griefing attack succeeds

**Search Queries**:
```
Grep("\\.call\\(|\\.delegatecall\\(", glob="**/*.sol")
Grep("gasleft\\(\\)", glob="**/*.sol")
```

**Mitigation**:
```solidity
// SECURE: Limit gas forwarded
(bool success,) = target.call{gas: 50000}(data);
// OR use try/catch
try ICallback(target).callback{gas: 50000}(data) {} catch {}
```

### Pattern 4: Block Stuffing

**Risk**: Attacker fills blocks to prevent time-sensitive operations

```solidity
// VULNERABLE: Time-sensitive operation
function claimAuction() external {
    require(block.timestamp >= auctionEnd, "Auction ongoing");
    require(!claimed, "Already claimed");
    claimed = true;
    // Transfer winning bid...
}
```

**Attack Flow**:
1. Attacker sees they're losing auction
2. Before auction ends, attacker submits many high-gas transactions
3. Blocks become full, legitimate claimAuction() can't execute
4. Attacker extends effective auction time
5. Eventually claims at manipulated state

**Mitigation**:
- Add grace periods for time-sensitive operations
- Use commit-reveal for auctions
- Allow partial execution

### Pattern 5: Storage Collision DoS

**Root Cause**: Unlimited Mapping/Array Growth

```solidity
// VULNERABLE: Unlimited storage per user
function addOrder(uint256 amount) external {
    userOrders[msg.sender].push(Order(amount, block.timestamp));
}

function cancelAllOrders() external {
    delete userOrders[msg.sender];  // @audit Gas increases with array size
}
```

**Attack Flow**:
1. Attacker creates millions of tiny orders
2. Tries to cancel all (or system tries to process)
3. Gas exceeds limits
4. Operations blocked

**Search Queries**:
```
Grep("push\\(|delete.*\\[", glob="**/*.sol")
Grep("mapping.*\\[\\]|address.*=>.*\\[\\]", glob="**/*.sol")
```

### Pattern 6: Return Bomb Attack

**Root Cause**: Unbounded Return Data

```solidity
// VULNERABLE: Copies all return data
function executeCall(address target, bytes calldata data) external returns (bytes memory) {
    (bool success, bytes memory result) = target.call(data);  // @audit result can be huge
    require(success);
    return result;
}
```

**Attack Flow**:
1. Attacker creates contract returning massive data (e.g., 1MB)
2. Memory expansion costs explode
3. Transaction runs out of gas
4. Call fails unexpectedly

**Mitigation**:
```solidity
// SECURE: Limit return data or use assembly
assembly {
    let success := call(gas(), target, 0, add(data, 32), mload(data), 0, 0)
    // Only copy limited return data if needed
}
```

---

## DoS Prevention Checklist

### Loop Safety
- [ ] All loops have bounded iterations
- [ ] Maximum batch size enforced
- [ ] Pagination available for large datasets
- [ ] Gas estimation includes worst case

### External Call Safety
- [ ] Pull pattern over push pattern
- [ ] Individual call failures don't block others
- [ ] Gas limits on external calls
- [ ] Fallback handling for failed transfers

### Storage Safety
- [ ] No unbounded arrays per user
- [ ] Cleanup mechanisms exist
- [ ] View functions handle large data

### Time Safety
- [ ] Grace periods for time-sensitive ops
- [ ] No strict time windows attackers can exploit
- [ ] Block stuffing resistance

---

## Search Query Reference

```
# Find unbounded loops
Grep("for.*\\.length|while.*length", glob="**/*.sol")
Grep("for.*i\\+\\+.*\\{", glob="**/*.sol")

# Find external calls
Grep("\\.call\\{|\\.transfer\\(|\\.send\\(", glob="**/*.sol")
Grep("require\\(success", glob="**/*.sol")

# Find storage patterns
Grep("push\\(|pop\\(|delete", glob="**/*.sol")
Grep("mapping.*\\[\\]", glob="**/*.sol")

# Find time dependencies
Grep("block\\.timestamp|block\\.number", glob="**/*.sol")
```

---

## Severity Classification

### Critical
- Funds permanently locked
- Core protocol functions uncallable
- No recovery mechanism

### High
- Temporary protocol freeze possible
- Significant gas griefing impact
- User funds at risk

### Medium
- View functions can fail
- Minor operations blockable
- Recovery exists but costly

---

## Rationalization Table (Reject These Excuses)

| Excuse | Reality |
|--------|---------|
| "Array won't grow that large" | Attackers WILL grow it. Assume worst case. |
| "Users won't create malicious contracts" | Attackers absolutely will. Every address is suspect. |
| "Gas is cheap" | Block gas limit is fixed. 30M gas max per block. |
| "We can upgrade if needed" | Funds may be locked BEFORE you can upgrade. |
| "This is theoretical" | Akropolis, SpankChain, and others lost millions to DoS. |
| "View functions don't matter" | External protocols depend on your views. DoS spreads. |

