DEV Community

ohmygod
ohmygod

Posted on

The DeFi War Room: A Battle-Tested Incident Response Playbook for Protocol Teams Under Active Exploit

In March 2026 alone, DeFi protocols have hemorrhaged over $55 million to exploits — from Solv Protocol's $2.7M ERC-3525 reentrancy to Aave's $50M slippage catastrophe and Curve's $239K oracle manipulation. Yet most protocol teams still have no documented incident response plan. When the exploit alert fires at 3 AM, they're improvising under maximum stress with millions on the line.

This article provides the concrete, step-by-step playbook that every DeFi protocol team should have printed, laminated, and taped to their monitors before the inevitable happens.


Phase 0: The Golden Five Minutes (T+0 to T+5)

The first five minutes determine whether you lose $500K or $50M. Every second of deliberation is money leaving the protocol.

Immediate Actions Checklist

□ CONFIRM the exploit (not a false alarm from monitoring)
□ ACTIVATE the war room (dedicated Telegram/Discord channel)  
□ PAUSE the protocol (if pause mechanism exists)
□ NOTIFY core team members (phone calls, not messages)
□ DO NOT post publicly yet
Enter fullscreen mode Exit fullscreen mode

The Pause Decision Tree

Is the exploit actively draining funds RIGHT NOW?
├── YES → Pause immediately. Ask questions later.
│         Call pauseAll() / emergencyShutdown()
│         If multisig required: get signers NOW (phone calls)
│
└── NO (exploit occurred in past / conditions not yet met)
    ├── Can it be replicated? → Pause preventively
    └── One-time condition? → Assess before pausing
Enter fullscreen mode Exit fullscreen mode

Critical mistake teams make: Waiting for consensus before pausing. The Euler Finance team's 13-minute response time in 2023 was considered fast — but $197M had already left. If you have a pause mechanism, use it first and debate later.

Code: Emergency Pause Pattern (Solidity)

// The pause guardian should be a single EOA for speed,
// NOT a multisig for emergency pause
contract ProtocolCore is Pausable {
    address public pauseGuardian;

    modifier onlyPauseAuthority() {
        require(
            msg.sender == pauseGuardian || 
            msg.sender == owner(),
            "Not authorized to pause"
        );
        _;
    }

    function emergencyPause() external onlyPauseAuthority {
        _pause();
        emit EmergencyPaused(msg.sender, block.timestamp);
        // Emit detailed event for post-mortem
    }

    // Unpause requires multisig (higher security for resumption)
    function unpause() external onlyOwner {
        _unpause();
    }
}
Enter fullscreen mode Exit fullscreen mode

For Solana Programs: Emergency Halt

// Anchor pattern for emergency pause
#[account]
pub struct ProtocolState {
    pub authority: Pubkey,
    pub pause_guardian: Pubkey,
    pub is_paused: bool,
    pub paused_at: i64,
    pub pause_reason: [u8; 64],
}

pub fn emergency_pause(ctx: Context<EmergencyPause>, reason: String) -> Result<()> {
    let state = &mut ctx.accounts.protocol_state;

    require!(
        ctx.accounts.signer.key() == state.pause_guardian 
        || ctx.accounts.signer.key() == state.authority,
        ErrorCode::Unauthorized
    );

    state.is_paused = true;
    state.paused_at = Clock::get()?.unix_timestamp;

    // Store reason for post-mortem
    let reason_bytes = reason.as_bytes();
    let len = reason_bytes.len().min(64);
    state.pause_reason[..len].copy_from_slice(&reason_bytes[..len]);

    msg!("EMERGENCY PAUSE: {}", reason);
    Ok(())
}

// Every instruction should check this
pub fn check_not_paused(state: &ProtocolState) -> Result<()> {
    require!(!state.is_paused, ErrorCode::ProtocolPaused);
    Ok(())
}
Enter fullscreen mode Exit fullscreen mode

Phase 1: Triage and Containment (T+5 to T+30)

You've paused. Now figure out what happened and stop the bleeding from secondary vectors.

The Triage Framework

Answer these questions in order:

Question Why It Matters
What function was exploited? Scope the damage surface
Is the attacker's address a contract or EOA? Contract = automated, expect more txs
How much has been taken? Sets the severity level
Are funds still in the attacker's wallet? Recovery opportunity window
Are other protocols affected? (composability) Coordinate disclosure
Is the exploit replicable on other chains? (if multichain) Pause everywhere

Transaction Forensics Checklist

# EVM: Trace the exploit transaction
cast run <TX_HASH> --trace  # Foundry
# Or use Tenderly/Phalcon for visual trace

# Identify the attacker
cast call <ATTACKER_CONTRACT> "owner()(address)" --rpc-url $RPC

# Check if attacker is still active
cast balance <ATTACKER_ADDRESS> --rpc-url $RPC

# For Solana: Use Helius or Solana Explorer
# Check transaction details
solana confirm -v <TX_SIGNATURE> --url mainnet-beta
Enter fullscreen mode Exit fullscreen mode

Contact List (Have This Ready BEFORE an Incident)

## Internal
- [ ] CTO / Lead Dev: [phone number]
- [ ] Smart Contract Lead: [phone number]  
- [ ] DevOps / Infrastructure: [phone number]
- [ ] Communications Lead: [phone number]
- [ ] Legal Counsel: [phone number]

## External (Security Partners)
- [ ] Audit firm (primary): [contact]
- [ ] Audit firm (secondary): [contact]
- [ ] SEAL 911 (Emergency response): https://seal911.org
- [ ] Chainalysis / TRM Labs (tracing): [contact]
- [ ] Bridge operators (if cross-chain): [contacts]

## Chain-Specific
- [ ] Block builder contacts (for MEV protection)
- [ ] Validator contacts (for Solana: leader schedule awareness)
- [ ] CEX security teams (for freezing funds)
Enter fullscreen mode Exit fullscreen mode

SEAL 911 is the single most important contact for DeFi teams. It's a volunteer group of top security researchers who respond to active exploits in real-time. Join their Telegram and have the link bookmarked.


Phase 2: Analysis and Recovery Planning (T+30 to T+4h)

Root Cause Analysis Template

Every post-mortem should answer:

## Root Cause Analysis

### The Bug
- **Vulnerability type:** [reentrancy / oracle manipulation / access control / logic error]
- **Affected contract(s):** [addresses]
- **Affected function(s):** [function signatures]
- **Introduced in:** [commit hash / deployment date]
- **Audit coverage:** [was this code audited? by whom? was this flagged?]

### The Exploit
- **Attacker address(es):** [list]
- **Attack transaction(s):** [list with links]
- **Attack contract:** [address, if applicable]
- **Funds stolen:** [amount in USD at time of exploit]
- **Exploit flow:**
  1. [Step-by-step description]
  2. ...

### Why It Wasn't Caught
- [ ] Not in audit scope
- [ ] Auditor missed it
- [ ] Introduced after audit
- [ ] Known risk, accepted
- [ ] Monitoring didn't detect it
- [ ] Detected but response too slow
Enter fullscreen mode Exit fullscreen mode

The Recovery Decision Matrix

Funds still in attacker wallet?
├── YES
│   ├── Attacker is a known entity → Legal action + negotiate
│   ├── Attacker wallet is a contract → Check for rescue vectors
│   │   └── Can you front-run a withdrawal? → White-hat rescue
│   └── Funds moving to CEX → Contact exchange security teams
│       (Binance, Coinbase, Kraken all have security@ emails)
│
└── NO (funds already moved)
    ├── Through Tornado Cash / mixer → Recovery unlikely
    ├── Through bridge → Contact destination chain teams
    └── To CEX → Freeze request (legal + direct contact)
Enter fullscreen mode Exit fullscreen mode

The Bounty Offer

Many exploits end with negotiated returns. The standard approach:

## On-Chain Message Template (send as tx input data)

To the person/team who exploited [Protocol Name]:

We have identified you as the person responsible for the exploit 
of [Protocol] on [date]. We are offering a [10-15]% white-hat 
bounty of [$ amount] if you return the remaining funds to 
[treasury address] within 48 hours.

If funds are returned, we will:
- Pay the bounty immediately
- Not pursue legal action
- Credit you as a white-hat if desired

If funds are NOT returned within 48 hours, we will:
- Engage law enforcement
- Work with blockchain analytics firms to trace and identify you
- Pursue all available legal remedies

Contact: [secure email] or [Telegram handle]
Treasury address: [address]
Enter fullscreen mode Exit fullscreen mode

Phase 3: Communication (Parallel to Phase 1-2)

The Communication Timeline

Time Action Channel
T+0 to T+30m Say nothing publicly Internal only
T+30m Brief acknowledgment Twitter/X
T+2h Detailed situation update Twitter/X + Discord
T+24h Full incident report Blog + all channels
T+7d Post-mortem with fix plan Blog + governance
T+30d Compensation plan (if applicable) Governance proposal

Template: Initial Acknowledgment (T+30m)

We are aware of an incident affecting [Protocol Name] and are 
actively investigating. The protocol has been paused as a 
precautionary measure. User funds are our top priority.

We will provide a detailed update within 2 hours.

Do NOT interact with any contracts claiming to offer refunds.
Enter fullscreen mode Exit fullscreen mode

What NOT to Do

  1. Don't blame users. Even if a user did something foolish (like Aave's $50M slippage trader), your protocol should have guardrails.
  2. Don't speculate on the attacker's identity publicly. Legal liability.
  3. Don't promise compensation before you know the full scope.
  4. Don't delete Discord messages asking about the exploit. Transparency builds trust.
  5. Don't rush to unpause. A second exploit after resumption destroys all remaining credibility.

Phase 4: Fix, Verify, and Resume (T+24h to T+7d)

The Resume Checklist

□ Root cause fully understood and documented
□ Fix implemented and tested
□ Fix reviewed by DIFFERENT auditor than original (fresh eyes)
□ Formal verification of critical invariants (if applicable)
□ Monitoring upgraded to detect similar patterns
□ Circuit breakers added (rate limits, max withdrawal per block)
□ Governance approval obtained (if applicable)
□ War game: can the fix be bypassed?
□ Staged rollout plan (testnet → limited mainnet → full)
□ Communication plan for resumption
Enter fullscreen mode Exit fullscreen mode

Post-Fix Monitoring Upgrades

After every incident, your monitoring should gain new detectors:

# Example: Alert on anomalous withdrawal patterns
class ExploitDetector:
    def __init__(self, protocol_address, alert_callback):
        self.protocol = protocol_address
        self.alert = alert_callback
        self.baseline_withdrawal = self.calculate_baseline()

    def check_transaction(self, tx):
        withdrawal_amount = self.parse_withdrawal(tx)

        # Alert if single withdrawal > 10x average
        if withdrawal_amount > self.baseline_withdrawal * 10:
            self.alert(
                severity="CRITICAL",
                message=f"Anomalous withdrawal: {withdrawal_amount}",
                tx_hash=tx.hash,
                action="CONSIDER IMMEDIATE PAUSE"
            )

        # Alert if same address withdraws > 3x in 10 blocks  
        recent_count = self.count_recent_withdrawals(
            tx.sender, blocks=10
        )
        if recent_count >= 3:
            self.alert(
                severity="HIGH",
                message=f"Rapid withdrawal pattern: {tx.sender}",
                tx_hash=tx.hash,
                action="INVESTIGATE IMMEDIATELY"
            )
Enter fullscreen mode Exit fullscreen mode

Pre-Incident Preparation: The Security Readiness Score

Rate your protocol (1 point each):

□ Pause mechanism exists and is tested monthly
□ Pause guardian is a single signer (not multisig) for speed
□ Unpause requires multisig or timelock
□ SEAL 911 contact established
□ On-call rotation with phone numbers (not just Telegram)
□ Transaction monitoring with automated alerts (Forta/OpenZeppelin Defender/custom)
□ Circuit breakers on critical functions (max amount per tx/block)
□ Incident response playbook documented and distributed
□ War game / tabletop exercise conducted quarterly
□ Bug bounty program active (Immunefi/HackerOne)
□ Multiple audit firms used across protocol lifetime
□ Insurance coverage (Nexus Mutual / InsurAce)

Score: ___/12
- 10-12: Well prepared
- 7-9: Decent but gaps exist  
- 4-6: Significant risk
- 0-3: It's not if, it's when
Enter fullscreen mode Exit fullscreen mode

Real-World Lessons from March 2026

Solv Protocol ($2.7M) — The Double-Mint

What happened: An ERC-3525 Semi-Fungible Token deposit path allowed minting shares twice for a single deposit when a full SFT was provided.

IR lesson: The exploit affected ~10 users. Solv's team committed to full compensation within 24 hours — the gold standard for user trust recovery.

What they did right:

  • Immediate pause after detection
  • Clear, honest communication
  • Compensation commitment before full post-mortem

Curve sDOLA ($239K) — The Donation Attack

What happened: The sDOLA token's donate() function allowed direct price manipulation of the ERC4626 vault share price, which Llamalend used as an oracle.

IR lesson: Composability risk is underestimated. Your protocol is only as secure as the tokens and oracles it integrates with.

Preventive measure: Price deviation checks and TWAP-based oracle fallbacks should be mandatory for any lending market accepting yield-bearing tokens.

Aave Slippage ($50M) — Not a Hack, But a Design Gap

What happened: A whale tried to swap $50M USDT through Aave's interface, got sandwiched by MEV bots, and lost nearly everything to slippage.

IR lesson: Even if "the user ignored warnings," your protocol's UX is your last line of defense. Hard-cap swap sizes. Add confirmation friction proportional to risk. Make it impossible for users to catastrophically self-harm.


Conclusion: Your Protocol WILL Be Tested

The question isn't whether your protocol will face a security incident — it's whether you'll respond in a way that preserves user trust and minimizes damage. The protocols that survive exploits and come back stronger are the ones that had a plan before the alert fired.

Print this playbook. Adapt it to your protocol. Run a tabletop exercise this week. Because the next $50M exploit isn't a matter of if — it's a matter of when.


This article is part of the DeFi Security series by DreamWork Security. Follow for weekly deep-dives into smart contract vulnerabilities, audit techniques, and security best practices.

Tags: #security #defi #blockchain #bestpractices

Top comments (0)