Skip to main content
ClaudeWave
Skill55 repo starsupdated 4mo ago

flashloan

>

Install in Claude Code
Copy
git clone --depth 1 https://github.com/PurpleAILAB/Vigilo /tmp/flashloan && cp -r /tmp/flashloan/packages/opencode/skills/flashloan ~/.claude/skills/flashloan
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Flash Loan Attack Patterns

This skill provides comprehensive knowledge for identifying flash loan attack vulnerabilities in smart contracts.

## Overview

Flash loans provide unlimited capital for a single transaction. Any logic that depends on current state (balances, prices, voting power) without proper protection is potentially vulnerable.

## Why Flash Loan Attacks Happen (Root Causes)

### Root Cause 1: Atomic Transaction Assumption Violation

Developers assume state remains consistent within a transaction. Flash loans break this assumption by allowing unlimited capital injection and withdrawal within a single block.

```solidity
// VULNERABLE: Assumes balance is stable within transaction
function liquidate(address user) external {
    uint256 collateral = collateralBalance[user];  // @audit Can be inflated
    uint256 debt = debtBalance[user];
    require(debt > collateral * LTV, "Healthy");
    // Liquidate...
}

// Attacker's flow:
// 1. Flash loan 1M tokens
// 2. Deposit as collateral → collateralBalance[attacker] += 1M
// 3. Call liquidate(victim) at manipulated state
// 4. Withdraw collateral
// 5. Repay flash loan
```

**Attacker's view**: "I can temporarily inflate any balance-based metric within a single transaction. The contract assumes state is stable, but I control it."

### Root Cause 2: Balance-Based Logic Without Time Lock

Any function that reads balances (token, collateral, voting power) and makes decisions in the same transaction is vulnerable.

```solidity
// DANGEROUS: Balance read and action in same tx
function borrow(uint256 amount) external {
    uint256 collateralValue = getCollateralValue(msg.sender);  // @audit Flashloan-inflatable
    require(amount <= collateralValue * LTV, "Insufficient collateral");
    _borrow(amount);
}

function getCollateralValue(address user) public view returns (uint256) {
    return token.balanceOf(address(this)) * userShare[user] / totalShares;
}
```

**Attacker's view**: "I deposit tokens, borrow against them, then withdraw. The contract never checks if I actually own the collateral after the transaction."

### Root Cause 3: Price Derivation from Manipulable Sources

Spot prices from DEXes can be manipulated within a single block via flash loans.

```solidity
// DANGEROUS: Spot price from AMM
function getPrice() public view returns (uint256) {
    (uint112 reserve0, uint112 reserve1,) = pair.getReserves();
    return reserve1 * 1e18 / reserve0;  // @audit Manipulable!
}

function liquidate(address user) external {
    uint256 price = getPrice();  // Attacker controls this
    uint256 collateralValue = collateral[user] * price;
    require(debt[user] > collateralValue, "Healthy");
    // Liquidate at wrong price...
}
```

**Attacker's view**: "I flash loan one side of the pair, dump it to crash the price, then liquidate at the manipulated rate."

### Root Cause 4: Governance Without Historical Snapshots

Voting power based on current balance allows flash loan governance attacks.

```solidity
// DANGEROUS: Current balance voting
function castVote(uint256 proposalId, bool support) external {
    uint256 votes = token.balanceOf(msg.sender);  // @audit Flash loanable!
    _recordVote(proposalId, msg.sender, votes, support);
}
```

**Attacker's view**: "I flash loan governance tokens, vote with them, then repay. The proposal passes with my temporary voting power."

---

## Attack Categories

### 1. Price Manipulation Attacks

**Root Cause**: Root Cause 3 (Price Derivation from Manipulable Sources)

**Vulnerable Pattern:**
```solidity
// DANGEROUS: Spot price from AMM
function getPrice() public view returns (uint256) {
    (uint112 reserve0, uint112 reserve1,) = pair.getReserves();
    return reserve1 * 1e18 / reserve0;
}

function liquidate(address user) external {
    uint256 price = getPrice(); // Manipulable!
    uint256 collateralValue = collateral[user] * price;
    require(debt[user] > collateralValue, "Healthy");
    // Liquidate...
}
```

**Attack Flow:**
```
1. Flash loan large amount of token0
2. Dump into AMM → reserve1/reserve0 crashes
3. Call liquidate() at manipulated price
4. Buy back token0 cheap
5. Repay flash loan
6. Profit from unfair liquidation
```

**Detection:**
```
Grep("getReserves|slot0\\(\\)|sqrtPriceX96", glob="**/*.sol")
```

---

### 2. Governance Manipulation

**Root Cause**: Root Cause 4 (Governance Without Historical Snapshots)

**Vulnerable Pattern:**
```solidity
// DANGEROUS: Balance-based voting
function castVote(uint256 proposalId, bool support) external {
    uint256 votes = token.balanceOf(msg.sender); // Flash loanable!
    _recordVote(proposalId, msg.sender, votes, support);
}
```

**Secure Pattern:**
```solidity
// Use snapshot at proposal creation
function castVote(uint256 proposalId, bool support) external {
    uint256 snapshotBlock = proposals[proposalId].snapshotBlock;
    uint256 votes = token.getPastVotes(msg.sender, snapshotBlock);
    _recordVote(proposalId, msg.sender, votes, support);
}
```

**Detection:**
```
Grep("balanceOf.*vote|vote.*balanceOf", glob="**/*.sol")
Grep("propose|castVote|delegate", glob="**/*.sol")
```

---

### 3. Collateral Manipulation

**Root Cause**: Root Cause 2 (Balance-Based Logic Without Time Lock)

**Vulnerable Pattern:**
```solidity
// DANGEROUS: Instant collateral increase
function borrow(uint256 amount) external {
    uint256 collateralValue = getCollateralValue(msg.sender);
    require(amount <= collateralValue * LTV, "Insufficient collateral");
    // Borrow...
}

function getCollateralValue(address user) public view returns (uint256) {
    return token.balanceOf(address(this)) * userShare[user] / totalShares;
    // ↑ Can be inflated with flash loan deposit
}
```

**Attack Flow:**
```
1. Flash loan tokens
2. Deposit as collateral → inflate collateralValue
3. Borrow maximum amount
4. Withdraw collateral
5. Repay flash loan (but keep borrowed funds)
```

---

### 4. Reward Manipulation

**Root Cause**: Root Cause 2 (Balance-Based Logic Without Ti