🌳 Advanced ⏱️ ongoing

Damn Vulnerable DeFi — Real DeFi Exploits

After Ethernaut, Damn Vulnerable DeFi (DVDF) is where your training becomes serious. Created by tinchoabbate (The Red Guild), every challenge replicates a real DeFi vulnerability class that has caused actual losses. Where Ethernaut teaches individual opcodes and simple patterns, DVDF teaches you to think like a DeFi attacker — across protocols, across flash loans, across governance systems.

Why DVDF Is Harder Than Ethernaut

FeatureEthernautDamn Vulnerable DeFi
DifficultyBeginner to intermediateIntermediate to advanced
Protocol complexitySingle contractsMulti-contract DeFi systems
Flash loansNot requiredCore mechanic in many levels
Capital requiredNone (simple calls)Flash loans provide unlimited capital
Attack styleSingle transaction usuallyComplex multi-step transactions
SetupBrowser + MetaMaskFoundry (local) recommended
Real analoguesHistorical bugsCurrent DeFi attack patterns
Time per challenge30 min - 2 hrs2 hrs - 2 days

DeFi Primitives You Must Know First

Before attempting DVDF, you need solid understanding of these DeFi building blocks:

📖 DeFi Primitives Quick Reference
1. AMMs (Automated Market Makers) — e.g., Uniswap x * y = k (constant product formula) - Liquidity providers deposit token pairs - Price determined by pool ratio (not orderbook) - Slippage: large trades move price unfavorably - Oracle risk: price can be manipulated in a block 2. Lending Protocols — e.g., Aave, Compound - Deposit collateral → borrow other assets - Health factor = collateral value / borrowed value - Liquidation if health factor drops below 1 - Interest rates: algorithmic, based on utilization 3. Flash Loans - Borrow ANY amount with NO collateral - Must repay principal + fee in the SAME transaction - If not repaid: entire transaction reverts (no risk to protocol) - Used legitimately for: arbitrage, collateral swaps, liquidations - Used maliciously for: price manipulation, governance attacks 4. Governance Tokens - Token holders vote on protocol changes - Voting power proportional to token balance - Flash loan + governance = massive voting power for one block 5. Price Oracles - Smart contracts that report asset prices - On-chain: derived from AMM pool ratios (manipulable) - Off-chain: Chainlink (cryptographically secure, not manipulable)

Flash Loans — Mechanics in Depth

⚡ Flash Loan Execution Flow
Flash Loan Flow (Aave V3 pattern): ┌─────────────────────────────────────────────────────────┐ │ Single Transaction │ │ │ │ 1. Attacker calls flashLoan(amount) │ │ ↓ │ │ 2. Pool transfers 'amount' tokens to Attacker │ │ ↓ │ │ 3. Pool calls executeOperation() on Attacker │ │ ↓ │ │ 4. *** Attacker has the funds — do anything here *** │ │ - Manipulate price oracles │ │ - Vote in governance │ │ - Liquidate undercollateralized positions │ │ - Drain other contracts │ │ ↓ │ │ 5. Attacker repays amount + fee (0.05-0.09%) │ │ ↓ │ │ 6. Pool checks: repaid in full? YES → tx succeeds │ │ NO → entire tx REVERTS│ └─────────────────────────────────────────────────────────┘ Key insight: Between steps 3-5, attacker can do ANYTHING with amounts far exceeding their capital (e.g., $1B flash loans exist)
💻 Generic Flash Loan Attack Template
// Generic flash loan attacker (Aave V3 pattern) contract FlashLoanAttacker is IFlashLoanSimpleReceiver { address immutable POOL; address immutable TOKEN; constructor(address pool, address token) { POOL = pool; TOKEN = token; } function attack() external { // Borrow as much as the pool has uint256 amount = IERC20(TOKEN).balanceOf(POOL); IFlashLoanPool(POOL).flashLoanSimple( address(this), // receiver TOKEN, // asset amount, // amount "", // params 0 // referral code ); } // Called by pool AFTER sending us the tokens function executeOperation( address asset, uint256 amount, uint256 premium, // fee amount address, // initiator (ignored) bytes calldata // params (ignored) ) external returns (bool) { // *** YOUR ATTACK LOGIC HERE *** // At this point we have 'amount' tokens // Example: manipulate oracle, liquidate, drain victim // Repay: approve pool to take back amount + fee uint256 amountOwed = amount + premium; IERC20(asset).approve(POOL, amountOwed); return true; // Signal successful execution } }

The 7 Most Important DVDF Challenges

1. Unstoppable — Flash Loan Griefing

📖 Challenge Concept

The pool counts its token balance using a storage variable. But what if someone sends tokens directly to the contract (not through the deposit function)? The storage variable would no longer match the actual token balance. When the flash loan function checks the two values are equal, it reverts. A simple 1-token transfer breaks the protocol forever — this is a DoS via invariant violation, not a fund theft.

💥 Unstoppable — The Pattern
// The vulnerable check in UnstoppableVault: uint256 balanceBefore = totalAssets(); // ... flash loan executes ... if (convertToShares(totalSupply) != balanceBefore) revert InvalidBalance(); // If accounting variable != actual balance, every flash loan reverts // Attack: transfer 1 token directly to the pool (bypassing deposit()) // Now: accounting says X, actual balance is X+1 → PERMANENT DoS

2. Naive Receiver — Flash Loan Fee Drain

📖 Challenge Concept

A receiver contract has ETH but its flash loan callback anyone can trigger. The fee is 1 ETH per flash loan call. The attacker keeps initiating flash loans on behalf of the victim receiver — each call costs the receiver 1 ETH in fees. After 10 calls, the receiver is drained. The vulnerability: the receiver doesn't check who initiated the flash loan.

3. Truster — Arbitrary Call Exploit

📖 Challenge Concept

The flash loan pool allows the borrower to specify an arbitrary target and data for a call() after lending. The attacker uses this to make the POOL itself call approve(attacker, MAX_UINT) on the token. After the flash loan ends (and attacker repays), the attacker calls transferFrom(pool, attacker, pool_balance). The pool approved itself — now the attacker drains it in a second transaction.

💥 Truster — Arbitrary Call Exploit Pattern
// Pool allows arbitrary call in its name during flash loan: pool.flashLoan( 0, // borrow 0 — we don't need the funds attacker, // borrower address (doesn't matter) address(token), // target: the token contract itself abi.encodeWithSignature( "approve(address,uint256)", attacker, type(uint256).max // Give attacker unlimited allowance FROM the pool ) ); // Now pool has approved attacker to spend pool's tokens // In next tx: token.transferFrom(pool, attacker, token.balanceOf(pool))

4. Side Entrance — Flash Loan Reentrancy

📖 Challenge Concept

The pool checks repayment by comparing ETH balance before and after the loan. During the flash loan callback, the attacker calls deposit() with the borrowed funds. This counts as "repayment" (balance is restored) but also credits the attacker's internal balance. After the flash loan, attacker calls withdraw() — draining the ETH that was just "deposited".

5. The Rewarder — Flash Loan + Reward Manipulation

📖 Challenge Concept

The reward pool distributes rewards proportional to deposited tokens at snapshot time. The attacker flash loans a massive amount of tokens, deposits them to claim a huge share of rewards, collects rewards, withdraws, and repays the flash loan — all in one transaction. No capital needed to steal a majority of the reward pool.

6. Selfie — Governance Manipulation

📖 Challenge Concept

The governance contract allows anyone with enough DVT tokens to queue an action. The attacker flash loans massive DVT, queues a drainAllFunds() governance proposal, repays the flash loan. 2 days later (after the governance delay), executes the proposal — draining the pool. Flash loans enable governance attacks even without actual token holdings.

7. Compromised — Oracle Price Manipulation

📖 Challenge Concept

This challenge gives you encoded private keys in what appears to be a server response. These keys belong to the trusted oracle signers. With oracle signing keys, you can set the NFT price to 0 ETH, buy all NFTs cheaply, set price to max, sell them back, and drain the exchange. Real-world analogues: compromised price feed keys have caused massive oracle manipulation losses.

Setting Up DVDF with Foundry

📦 DVDF Setup Steps
# Clone the DVDF repository (Foundry version) git clone https://github.com/tinchoabbate/damn-vulnerable-defi cd damn-vulnerable-defi # Install dependencies forge install # Verify tests run (all should FAIL initially — that's expected) forge test # Project structure: damn-vulnerable-defi/ ├── src/ # Vulnerable protocol contracts │ ├── unstoppable/ │ ├── naive-receiver/ │ └── ... ├── test/ # Challenge setup + validation │ ├── unstoppable/ │ │ └── Unstoppable.t.sol # Your solution goes here │ └── ... └── foundry.toml # Test structure in each challenge file: // setUp() — sets up the scenario (victims, funds, etc.) // test_xxxx() — your exploit goes here // _isSolved() — validation (must return true to pass) # Run a specific challenge: forge test --match-contract Unstoppable -vvvv

How to Approach a Challenge You're Stuck On

🧠 Challenge Methodology
Step 1: READ THE WIN CONDITION FIRST Open the test file and read _isSolved() This tells you exactly what state you need to achieve Example: attacker has all tokens + pool has 0 Step 2: MAP THE SYSTEM List all contracts in this challenge Identify: who holds what funds? what are the roles? Draw a diagram if needed Step 3: FIND ALL ENTRY POINTS What external/public functions can you call? What do they do to state? Can any of them be called by anyone? (missing access control) Step 4: LOOK FOR INVARIANT VIOLATIONS What invariants should ALWAYS hold? "Pool balance >= deposits" "Reward proportional to deposit" Can you violate one of these? Step 5: CONSIDER FLASH LOANS Do you need capital to break an invariant? Can you borrow it via flash loan? What's the sequence: borrow → exploit → repay? Step 6: BUILD AND TEST IN FOUNDRY Write your attacker contract Call it from the test Use console.log() to debug state at each step forge test -vvvv shows full execution trace

Key DeFi Vulnerability Categories in DVDF

CategoryDVDF LevelsReal-World ExampleTypical Loss
Flash Loan + GovernanceSelfie, Free RiderBeanstalk ($182M, 2022)$50M-$200M
Price Oracle ManipulationCompromised, PuppetMango Markets ($100M, 2022)$50M-$100M
ReentrancySide EntranceThe DAO ($60M, 2016)$10M-$100M
Arbitrary External CallsTrusterEuler Finance ($197M, 2023)$50M-$200M
Accounting InconsistencyUnstoppableMany DeFi protocols$1M-$50M
Fee GriefingNaive ReceiverRelay contract exploits$1M-$10M
Flash Loan + RewardsThe RewarderVarious yield protocols$5M-$50M

Common Mistakes Section

⚠️ Mistake #1: Trying DVDF Without Ethernaut Foundation

DVDF assumes you understand reentrancy, visibility, modifiers, and basic Solidity patterns. If you are jumping straight into DVDF without Ethernaut, you will struggle unnecessarily. Complete at least the first 10 Ethernaut levels before starting DVDF.

⚠️ Mistake #2: Forgetting That Flash Loans Can Fail

If your flash loan callback reverts for any reason — a failed call, a failed assertion, running out of gas — the ENTIRE transaction reverts including the flash loan itself. This means you need to test your exploit in full sequence in Foundry before committing to it. Use try/catch carefully and check all return values inside the callback.

⚠️ Mistake #3: Not Reading Protocol Code Before Attacking

Each DVDF challenge involves multiple contracts. Read ALL of them before writing any exploit code. The vulnerability is usually in an interaction between two contracts, not within a single contract. Missing the context of how contracts interact with each other leads to hours of wrong-direction exploration.

🚨 Ethical Note: Real Protocols Are Off-Limits

DVDF teaches you techniques that are directly applicable to real DeFi attacks. These skills exist to help you find and report vulnerabilities (through bug bounty programs) — not to exploit them for personal gain. Exploiting live DeFi protocols is illegal in most jurisdictions. Use these skills ethically: report bugs, earn bounties, protect users.

Summary / Key Takeaways

ConceptKey LessonHow to Apply
Flash loansUnlimited capital for one transactionAlways ask: "can a flash loan fund this attack?"
Price oraclesOn-chain prices are manipulableCheck if protocol uses Chainlink or spot price
Governance attacksFlash loans = instant voting powerLook for governance with no time-weighted balances
Accounting invariantsInternal accounting must match realityCheck all paths that change balances
Arbitrary callsUnvalidated calls let attacker take controlAny low-level .call() with attacker-controlled data is suspect
DVDF methodologyRead win condition → map system → find invariant violationApply to real audits too