关于 defi-attack-patterns
面向审查智能合约与协议设计的 DeFi 安全手册,供安全分析人员使用。内容涵盖闪电贷、预言机、MEV、治理、跨链桥及代币标准相关攻击模式。
主要功能
- 01闪电贷攻击机制
- 02现货与 TWAP 预言机风险
- 03MEV 提取模式
- 04精度损失与金库通胀攻击
- 05治理与跨链桥漏洞
- 06代币标准边缘情况
适用场景
- 01审查 DeFi 预言机设计
- 02评估金库份额计算
- 03分析治理投票保护措施
- 04审计跨链桥消息验证
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill defi-attack-patterns安装后在 Claude Code 中输入/defi-attack-patterns确认已加载。
详细介绍
技能:DeFi 攻击模式 — 专家攻击手册
AI 加载指令:DeFi 专家级攻击技术。涵盖闪电贷机制、预言机操纵(现货价格与 TWAP)、MEV 提取(夹击、JIT、清算)、精度损失攻击、治理漏洞利用、跨链桥漏洞以及代币标准陷阱。基础模型通常会忽略闪电贷必须在单笔交易中原子完成的约束,以及操纵现货价格与操纵 TWAP 之间的区别。
0. 相关路由
- smart-contract-vulnerabilities,了解底层 Solidity 漏洞模式(重入、整数溢出、delegatecall)
- deserialization-insecure,适用于攻击链下跨链桥中继器或索引器基础设施的情况
1. 闪电贷攻击
1.1 机制
闪电贷可在单笔交易中提供无抵押借款。整个借款 → 使用 → 还款周期必须以原子方式完成;如果还款失败,交易将回滚,效果就像什么都没有发生。
| 提供方 | 最大金额 | 费用 |
|---|---|---|
| Aave V3 | 每种资产的资金池流动性 | 0.05%(获批借款人可为 0) |
| dYdX | 资金池流动性 | 0(使用内部余额操纵) |
| Uniswap V3 | 每个交易对的资金池流动性 | 0.3%(交换费率档位) |
| Balancer | 资金池流动性 | 协议可配置 |
1.2 价格预言机操纵
1. Flash borrow 100,000 WETH
2. Swap 100,000 WETH → TOKEN on AMM_A
→ TOKEN spot price on AMM_A skyrockets
3. On Lending_Protocol (reads AMM_A spot price as oracle):
→ Deposit small TOKEN collateral (valued at inflated price)
→ Borrow large amount of WETH against it
4. Swap TOKEN back → WETH on AMM_A (restore price)
5. Repay flash loan (100,000 WETH + fee)
6. Keep borrowed WETH from Lending_Protocol minus collateral cost
关键要点:将 AMM 现货储备(getReserves())用作价格预言机的协议容易受到攻击。必须使用 TWAP 或外部预言机(Chainlink)。
1.3 通过重入抽干流动性池
闪电借款 → 存入资金池 → 在回调期间触发重入 → 提取超过存入金额的资金 → 偿还贷款。
此攻击利用了闪电贷资金与资金池记账逻辑中的重入漏洞的组合。
1.4 治理闪电借款
1. Flash borrow governance tokens
2. Create/vote on malicious proposal (if no snapshot or timelock)
3. Proposal passes instantly
4. Execute proposal (drain treasury, change admin, etc.)
5. Return governance tokens
防御措施:基于快照的投票(Compound Governor Bravo)、时间锁、最短提案期。
2. 价格预言机操纵
2.1 现货价格与 TWAP
| 预言机类型 | 操纵成本 | 时间窗口 |
|---|---|---|
现货价格(getReserves()) | 一笔大额交换(可通过闪电贷获得资金) | 同一笔交易 |
| TWAP(时间加权平均值) | 持续多个区块的操纵 | 多个区块(成本高) |
| Chainlink 聚合器 | 控制 ≥ 多数预言机节点 | 实际上不可行 |
2.2 AMM 操纵流程
Normal state: Pool has 1000 ETH + 1,000,000 USDC → price = 1000 USDC/ETH
Attack:
├── Swap 9000 ETH into pool
│ Pool now: 10000 ETH + 100,000 USDC (constant product)
│ Spot price: 10 USDC/ETH (crashed 100x)
├── Dependent contract reads this price
│ → Liquidates positions at wrong price
│ → Or allows cheap borrowing against ETH collateral
├── Swap back: buy ETH with USDC
│ Price restores to ~1000 USDC/ETH
└── Net profit = value extracted from dependent contract - swap slippage - fees
2.3 Chainlink 预言机数据过期
(, int price, , uint updatedAt, ) = priceFeed.latestRoundData();
// Missing checks:
// 1. price > 0
// 2. updatedAt != 0
// 3. block.timestamp - updatedAt < HEARTBEAT
// 4. answeredInRound >= roundId
如果预言机数据过期(网络拥堵、L2 排序器宕机),价格可能已滞后数小时 → 可针对过期价格进行套利。
L2 排序器风险:如果 Arbitrum/Optimism 排序器宕机,Chainlink 价格会冻结。排序器恢复后,价格会跳变 → 按错误价格发生大规模清算。
3. MEV(最大可提取价值)
3.1 夹击攻击
Mempool observation: victim submits swap TOKEN_A → TOKEN_B with slippage 1%
Front-run: Buy TOKEN_B (increase price)
Victim tx: Swap executes at worse price (within slippage tolerance)
Back-run: Sell TOKEN_B (profit from price impact)
Profit = victim's price impact - gas costs × 2
3.2 JIT(即时)流动性
1. Observe large pending swap in mempool
2. Provide concentrated liquidity in the exact price range (Uniswap V3 tick)
3. Victim's swap executes → JIT LP earns majority of fees
4. Remove liquidity immediately after swap
5. Profit = fee earned - gas - impermanent loss (minimal for single block)
3.3 清算 MEV
1. Monitor lending protocols for positions approaching liquidation threshold
2. When price oracle updates → position becomes liquidatable
3. Front-run other liquidators → execute liquidation
4. Receive liquidation bonus (typically 5-15% of collateral)
5. Sell collateral for profit
3.4 MEV 防护机制
| 机制 | 工作方式 |
|---|---|
| Flashbots Protect | 将交易发送到私有内存池;只有区块构建者能看到 |
| MEV Blocker | 通过支持 MEV 的中继器路由交易的 RPC 端点 |
| Cow Protocol(批量拍卖) | 批量撮合,消除交易排序优势 |
| 加密内存池 | 使用门限加密;仅在构建区块时解密 |
| MEV-Share | 用户获取从其交易中提取的部分 MEV |
4. 精度损失利用
4.1 代币计算中的舍入误差
Solidity 不支持浮点数。整数除法会截断:
shares = depositAmount * totalShares / totalAssets
如果相对于 depositAmount * totalShares 而言,totalAssets 非常大,结果会舍入为 0 → 存款人拿不到任何份额,但资金池会保留这笔存款。
4.2 首位存款人/金库膨胀攻击
1. Attacker deposits 1 wei → receives 1 share
2. Attacker donates 1,000,000 tokens directly to vault (not via deposit)
3. Vault state: 1,000,001 tokens, 1 share
4. Victim deposits 999,999 tokens:
shares = 999,999 * 1 / 1,000,001 = 0 (integer truncation)
5. Victim gets 0 shares; attacker owns 100% of vault (now 2,000,000 tokens)
6. Attacker withdraws all
防御措施:
- 首次存款时铸造死份额(OpenZeppelin ERC4626 offset)
- 要求最低初始存款额
- 使用带虚拟偏移的内部记账
4.3 通过精度截断进行尘埃攻击
重复进行小额操作,每次截断都会损失 1 wei。累积数千次操作后,损失将达到显著规模。
5. 治理攻击
5.1 闪电贷治理攻击
借入治理代币 → 投票 → 归还。只有在协议未于投票前对余额进行快照时才会奏效。
5.2 时间锁绕过
| 攻击途径 | 方法 |
|---|---|
| 时间锁设为 0 | 管理员可立即执行提案 |
emergencyExecute 函数 | 以“紧急情况”为由绕过时间锁 |
| Guardian/多签覆盖 | 单点故障 |
| 攻击者取消提案 | 达到门槛时抢先取消提案 |
5.3 法定人数操纵
Protocol requires 10% quorum (10M tokens out of 100M supply)
├── Flash borrow 10M governance tokens
├── Create proposal: set admin = attacker
├── Vote with borrowed tokens → meets quorum
├── If no timelock: execute immediately
└── Return tokens
6. 跨链桥漏洞利用
6.1 常见跨链桥攻击途径
| 攻击途径 | 示例 |
|---|---|
| 绕过签名验证 | Ronin Bridge(6.24 亿美元)——5/9 验证者遭到入侵 |
| 消息重放 | 在多条链上重放存款证明 |
| 伪造存款证明 | 提交不存在的 L1 存款证明 |
| 验证者串通 | 跨链桥验证者中的多数遭到入侵 |
| 智能合约漏洞 | Wormhole(3.2 亿美元)——Guardian 集未初始化 |
| 可升级代理漏洞利用 | 攻击者获得升级权限 → 替换实现合约 |
6.2 跨链消息验证
Secure pattern:
├── Source chain: emit event with (destination, amount, nonce, chainId)
├── Relayer: submit proof (Merkle proof of event inclusion)
├── Destination chain: verify proof against known source block header
│ ├── Check nonce not replayed
│ ├── Check chainId matches
│ ├── Verify Merkle proof against trusted root
│ └── Mint/release tokens
Vulnerable pattern:
├── Relayer: submit (destination, amount) signed by N-of-M validators
└── If M is small or keys are compromised → forge signatures
7. 代币标准边界情况
7.1 ERC-20 授权抢先交易
1. Alice approves Bob for 100 tokens
2. Alice wants to change approval to 50 tokens
3. Bob sees the approval change tx in mempool
4. Bob front-runs: transferFrom(Alice, Bob, 100) — uses old approval
5. Alice's approval change executes: approval = 50
6. Bob calls transferFrom(Alice, Bob, 50) — uses new approval
7. Bob extracted 150 tokens instead of 50
防御方法:先执行 approve(0),再执行 approve(newAmount)。或者使用 increaseAllowance/decreaseAllowance。
7.2 通过钩子触发 ERC-777 重入攻击
ERC-777 代币会在完成转账前,先调用接收方的 tokensReceived() 钩子 → 这是经典的重入攻击途径。
transfer(attacker, amount)
├── _beforeTokenTransfer hook
├── Balance update
├── tokensReceived() callback to recipient ← reentrancy window
│ └── attacker re-enters: transfer, swap, deposit, etc.
└── _afterTokenTransfer hook
7.3 转账收费代币
每次转账都会扣除费用的代币。协议收到的金额少于 amount:
// Vulnerable: assumes received == amount
token.transferFrom(msg.sender, address(this), amount);
deposits[msg.sender] += amount; // overcredits by fee amount
// Fixed: measure actual balance change
uint before = token.balanceOf(address(this));
token.transferFrom(msg.sender, address(this), amount);
uint received = token.balanceOf(address(this)) - before;
deposits[msg.sender] += received;
7.4 重基代币
自动调整余额的代币(例如 Aave aTokens、stETH)。如果协议缓存了余额,持有重基代币可能导致账目不匹配。
8. 值得关注的 DeFi 漏洞利用案例参考
| 漏洞利用案例 | 日期 | 损失 | 主要攻击途径 |
|---|---|---|---|
| Ronin Bridge | 2022 年 3 月 | 6.24 亿美元 | 验证者密钥遭到入侵 |
| Wormhole | 2022 年 2 月 | 3.2 亿美元 | 签名验证漏洞 |
| Beanstalk | 2022 年 4 月 | 1.82 亿美元 | 闪电贷治理攻击 |
| Mango Markets | 2022 年 10 月 | 1.14 亿美元 | 预言机操纵 |
| Euler Finance | 2023 年 3 月 | 1.97 亿美元 | 捐赠攻击 + 清算逻辑 |
| Curve(重入攻击) | 2023 年 7 月 | 7,300 万美元 | Vyper 编译器重入漏洞 |
9. 决策树
Analyzing a DeFi protocol?
├── Does it use price oracles?
│ ├── Spot price (AMM reserves)? → Flash loan manipulation (Section 1.2)
│ │ └── Can oracle be manipulated in single tx? → HIGH RISK
│ ├── TWAP? → Multi-block manipulation needed → MEDIUM RISK
│ ├── Chainlink? → Check staleness handling (Section 2.3)
│ │ ├── Heartbeat check present? → OK
│ │ └── L2? → Check sequencer uptime oracle
│ └── Multiple oracles with fallback? → Evaluate each
├── Does it accept external tokens?
│ ├── Yes → Check fee-on-transfer handling (Section 7.3)
│ ├── ERC-777 tokens accepted? → Reentrancy via hooks (Section 7.2)
│ └── Rebasing tokens? → Accounting mismatch (Section 7.4)
├── Does it have governance?
│ ├── Yes → Flash loan governance possible? (Section 5.1)
│ │ ├── Snapshot-based voting? → Safer
│ │ └── Live balance voting? → Flash borrow attack
│ ├── Timelock present? → Check for bypass (Section 5.2)
│ └── Quorum threshold vs flash-loanable supply? (Section 5.3)
├── Is it a vault / yield aggregator?
│ ├── Yes → First depositor attack (Section 4.2)
│ │ └── Virtual offset or dead shares? → Mitigated
│ └── Precision loss in share calculation? (Section 4.1)
├── Is it a bridge?
│ ├── Yes → Load bridge vectors (Section 6)
│ │ ├── Validator set size and key management?
│ │ ├── Replay protection (nonce + chainId)?
│ │ └── Upgradeable? → Who holds upgrade key?
│ └── No → Continue
├── User-facing swap functionality?
│ ├── Yes → MEV exposure (Section 3)
│ │ ├── Slippage protection enforced?
│ │ └── Private mempool integration?
│ └── No → Continue
└── Load [smart-contract-vulnerabilities](../smart-contract-vulnerabilities/SKILL.md)
for underlying Solidity-level bugs