---
name: solidity-defi
description: >
  DeFi プロトコル開発スキル。AMM・流動性プール、レンディング、
  価格オラクル、Vault（ERC4626）の設計パターンを提供する。
  ユーザーが "DeFi", "AMM", "DEX", "レンディング", "Vault",
  "流動性プール", "オラクル", "solidity-defi" 等と言った時に使用。
allowed_tools:
  - Read
  - Write
  - Edit
  - Bash
  - Glob
  - Grep
  - Task
  - AskUserQuestion
---

# solidity-defi: DeFi プロトコル開発スキル

DeFi プロトコル開発における主要パターン（AMM、レンディング、オラクル、Vault）を提供するドメイン特化スキル。

## 対象

- AMM / DEX（Uniswap V2/V3 型、Curve 型）
- レンディングプロトコル（Aave / Compound 型）
- 価格オラクル統合（Chainlink、TWAP）
- Vault / yield 戦略（ERC4626）

## ワークフロー

### Step 1: DeFi ドメイン判定

ユーザーの要件から対象ドメインを判定する:

| ユースケース | 対応ドメイン | リファレンス |
|------------|------------|------------|
| トークン交換・流動性提供 | AMM / DEX | `references/amm-patterns.md` — Constant Product (Uniswap V2)、Concentrated Liquidity (V3)、StableSwap (Curve) から選択 |
| 貸付・借入・清算 | レンディング | `references/lending-patterns.md` — 金利モデル、担保管理、清算メカニズムを確認 |
| 外部価格データ取得 | オラクル | `references/oracle-patterns.md` — Chainlink Data Feed、TWAP、複合オラクルから選択 |
| 預入・利回り・戦略 | Vault | `references/vault-patterns.md` — ERC4626 標準、inflation attack 防御、マルチ戦略 |

複数のドメインが関連する場合（例: Vault + オラクル）は、全ての該当リファレンスを読み込む。

ユーザーの要件が不明確な場合は AskUserQuestion で DeFi の具体的なユースケースを確認する。

**検証ゲート**: 対象ドメインが上記 4 つのいずれかに該当すること。

### Step 2: リファレンス読み込み

Step 1 で特定したリファレンスファイルを読み込み、以下を確認する:

1. 該当パターンの設計思想と制約条件
2. 必要なインターフェース（ERC4626、Chainlink AggregatorV3 等）
3. コード例の前提条件（Solidity バージョン、依存ライブラリ）

**検証ゲート**: リファレンスが正常に読み込め、該当パターンが特定できること。

### Step 3: コード生成

1. `solidity-core` の `language-patterns.md` に従い NatSpec・コーディング規約を適用する。
2. DeFi 固有のセキュリティ対策を組み込む:
   - 全ての state-changing 関数に `nonReentrant` 修飾子
   - スリッページ保護パラメータ（`minAmountOut`, `deadline`）
   - 適切な数値精度（WAD / RAY / BPS）
3. テストコードを同時に生成する:
   - 正常系（swap、deposit、withdraw）
   - 異常系（スリッページ超過、残高不足、権限不足）
   - Fuzz テスト（数値入力のある関数）
   - Invariant テスト（プールの不変条件: `k >= kBefore`）

**検証ゲート**: `forge build` がエラーなく完了すること。

### Step 4: DeFi セキュリティ確認

DeFi 特有のセキュリティリスクを `solidity-core` の `security-checklist.md` と合わせて確認する:

1. **フラッシュローン攻撃**: 1 トランザクション内での価格操作に耐性があるか。TWAP を使用しているか。
2. **価格操作**: オラクルがスポット価格のみに依存していないか。Chainlink の `latestRoundData` で stale check をしているか。
3. **Reentrancy**: CEI パターン + `nonReentrant` を遵守しているか。特に `withdraw` / `redeem` 関数。
4. **スリッページ保護**: ユーザーが `minAmountOut` を指定でき、フロントランニングから保護されているか。
5. **MEV 対策**: `deadline` パラメータでサンドイッチ攻撃のウィンドウを制限しているか。
6. **Inflation Attack（ERC4626）**: 初回デポジットのシェア膨張攻撃に対して virtual shares / virtual assets で防御しているか。

**検証ゲート**: CRITICAL レベルのセキュリティ問題が 0 件であること。

## 使用例

### 例 1: Uniswap V2 型 AMM の実装

**ユーザー入力**: 「シンプルな AMM を作りたい。流動性追加とトークンスワップができるようにして」

**アクション**:
1. Step 1: AMM / DEX と判定 → `references/amm-patterns.md` を選択
2. Step 2: Constant Product AMM パターンを読み込み
3. Step 3: 以下を生成:
   - `src/ConstantProductAMM.sol` — Pair コントラクト（`x * y = k` ロジック、`nonReentrant`、スリッページ保護）
   - `src/interfaces/IAMM.sol` — インターフェース定義
   - `test/ConstantProductAMM.t.sol` — addLiquidity / swap / removeLiquidity のテスト + K 値 invariant テスト
4. Step 4: セキュリティ確認 → Reentrancy 防止、スリッページ保護、K 値検証を確認

**結果**: スリッページ保護・Reentrancy 防止を備えた AMM とテストスイートが生成される。

### 例 2: ERC4626 Vault の実装

**ユーザー入力**: 「ERC4626 の Vault を作りたい。ETH ステーキングの利回りを分配するもの」

**アクション**:
1. Step 1: Vault と判定 → `references/vault-patterns.md` を選択
2. Step 2: ERC4626 標準 + inflation attack 防御パターンを読み込み
3. Step 3: 以下を生成:
   - `src/StakingVault.sol` — OpenZeppelin `ERC4626` を継承。virtual shares / virtual assets で inflation attack を防御。`deposit` / `withdraw` / `redeem` 実装
   - `test/StakingVault.t.sol` — デポジット・引出のテスト + 初回デポジット攻撃の防御テスト + share 計算の Fuzz テスト
4. Step 4: inflation attack 防御の確認、Reentrancy 確認

**結果**: Inflation attack に耐性のある ERC4626 Vault がテスト付きで生成される。

### 例 3: Chainlink オラクル統合

**ユーザー入力**: 「ETH/USD の価格を Chainlink で取得して、USD 建ての計算をしたい」

**アクション**:
1. Step 1: オラクルと判定 → `references/oracle-patterns.md` を選択
2. Step 2: Chainlink Data Feed パターンを読み込み
3. Step 3: 以下を生成:
   - `src/PriceConsumer.sol` — `AggregatorV3Interface` を使用。stale price チェック（`updatedAt` + 閾値）、negative price チェック、decimals 正規化
   - `test/PriceConsumer.t.sol` — モックオラクルでテスト。stale price / negative price / decimals 変換のテスト
4. Step 4: stale check の閾値（heartbeat 設定に基づく）、フォールバックオラクルの有無を確認

**結果**: Stale / negative price に対するガードを備えた Chainlink オラクル統合が生成される。

## トラブルシューティング

### 1. K 値 invariant テストが失敗する

**症状**: AMM の `require(k >= kBefore)` でリバート

**原因と対策**:
- **丸め誤差**: Solidity の整数除算による丸めで K 値が微小に減少する。`require(k >= kBefore - 1)` で許容誤差を設定するか、`mulDiv` 関数で精度を向上させる。
- **手数料計算の順序**: 手数料を差し引いてからスワップ計算を行っているか確認する。手数料を考慮した K 値検証にする。

### 2. Chainlink オラクルが stale 価格を返す

**症状**: `require(updatedAt > block.timestamp - STALE_THRESHOLD)` でリバート

**原因と対策**:
- **heartbeat 設定の不一致**: Chainlink の Data Feed ごとに heartbeat（更新間隔）が異なる。ETH/USD（Mainnet）は 3600 秒。対象 feed の heartbeat を確認し、`STALE_THRESHOLD` を heartbeat + バッファ（例: `3600 + 300`）に設定する。
- **テストネットの挙動**: テストネットの Chainlink feed は本番より更新が遅い場合がある。テストではモックオラクルを使用する。
- **フォールバック**: Chainlink が応答しない場合に備え、TWAP 等のフォールバックオラクルを設定する。

### 3. ERC4626 の share 計算がゼロになる

**症状**: `deposit` 後に `balanceOf(user)` がゼロ

**原因と対策**:
- **Inflation attack**: 攻撃者が最初に 1 wei をデポジット後、大量のトークンを直接 Vault に送信して share 価値を膨張させた。OpenZeppelin の `ERC4626` は v5.x でデフォルトで virtual shares/assets（オフセット = 1）を使用するため、最新版を使用する。
- **decimals の不一致**: 基礎トークンと Vault の decimals が異なる。`decimalsOffset()` を確認する。

### 4. swap トランザクションがフロントランされる

**症状**: 予想よりも不利なレートでスワップが実行される

**原因と対策**:
- **スリッページ保護の不足**: `minAmountOut` パラメータが 0 に設定されている。フロントエンドで適切なスリッページ（0.5-1%）を計算して設定する。
- **deadline 未設定**: `deadline` パラメータでトランザクションの有効期限を設定する。`block.timestamp + 300`（5分）が一般的。
- **Private mempool**: Flashbots Protect 等のプライベート RPC を使用し、パブリック mempool にトランザクションを公開しない。

### 5. Reentrancy による資金流出

**症状**: `withdraw` 関数が繰り返し呼び出され、想定以上の資金が引き出される

**原因と対策**:
- **CEI パターン違反**: 外部呼び出し（`token.transfer`）の前に状態を更新（残高減算）しているか確認する。Checks-Effects-Interactions の順序を厳守する。
- **`nonReentrant` 未使用**: 全ての資金移動関数に OpenZeppelin の `ReentrancyGuard.nonReentrant` を適用する。
- **コールバック関数**: ERC777 や `receive()` / `fallback()` からの再帰呼び出しに注意する。

## 注意事項

- DeFi プロトコルは攻撃対象になりやすいため、セキュリティを最優先にする。
- 数値計算は精度が重要。WAD（1e18）、RAY（1e27）、BPS（1e4）を一貫して使用する。
- 基盤的なパターン（アクセス制御、ガス最適化等）は `solidity-core` を参照する。
- フロントエンド統合は `web3-frontend` を参照する。
- 本番デプロイ前に外部監査を推奨する。
- OpenZeppelin コントラクト（`ERC4626`, `ReentrancyGuard` 等）の利用を推奨し、独自実装は避ける。
