MEV(最大抽出可能価値)完全解説 — Flashbots・Jito・MEV戦略の実践

上級
DeFiアルゴリズム取引Ethereum

MEVとは

MEV(Maximal Extractable Value / 最大抽出可能価値)とは、ブロック内のトランザクションの順序を操作することで得られる追加的な利益のことです。元々は「Miner Extractable Value」と呼ばれていましたが、EthereumがPoSに移行した後は「Maximal Extractable Value」と再定義されました。

MEVの基本概念

[通常のトランザクション処理]
ユーザーA: トランザクション送信 → メモリプール → ブロックに含まれる

[MEVが発生する場面]
ユーザーA: Uniswapで大量のETH→USDC スワップを送信
  → メモリプールで公開される
  → MEVサーチャーが検知
  → サーチャーが自分のTXをユーザーAの前後に挿入
  → 価格差から利益を抽出

MEVの規模

指標EthereumSolana
累計抽出MEV$6B以上$1B以上
日次MEV(平均)$2-5M$0.5-2M
アクティブサーチャー数数百数百
MEV保護利用率約30%約20%

MEVの種類

1. フロントランニング(Front-running)

ユーザーのトランザクションを検知し、先に同じ取引を実行して利益を得る手法です。

[フロントランニングの例]

ユーザー: Uniswapで10 ETH → USDC を実行予定
  現在のレート: 1 ETH = 3,000 USDC

MEVサーチャー:
  1. メモリプールでユーザーのTXを検知
  2. ユーザーの前に5 ETH → USDC を実行
     → レートが 1 ETH = 3,000.5 USDC に変動
  3. ユーザーのTXが実行される
     → レートが 1 ETH = 3,005 USDC に変動
  4. サーチャーはUSDC → ETH で戻す
     → 差額分(約$25)が利益

時系列:
  [サーチャーのTX] → [ユーザーのTX]
       ↑ フロントラン

2. バックランニング(Back-running)

特定のイベント(大口取引、オラクル更新、新トークンリスティング等)の直後にトランザクションを実行して利益を得る手法です。

[バックランニングの例: オラクル更新]

Chainlinkオラクル: ETH/USD価格を $3,000 → $3,050 に更新

MEVサーチャー:
  オラクル更新TXの直後に:
  1. Aave等で古い価格基準のポジションを清算
  2. 清算報酬(5-10%)を獲得

時系列:
  [オラクル更新TX] → [サーチャーの清算TX]
                         ↑ バックラン

3. サンドイッチ攻撃(Sandwich Attack)

フロントランニングとバックランニングを組み合わせ、ユーザーの取引を挟み込む手法です。最も一般的かつ議論の多いMEV戦略です。

[サンドイッチ攻撃の詳細]

ユーザー: USDCで100 ETH を購入(スリッページ許容: 0.5%)

攻撃者のアクション:
  TX1 (フロントラン): 50 ETH を購入 → 価格上昇
  TX2 (ユーザーのTX): 100 ETH を購入 → さらに価格上昇(不利なレート)
  TX3 (バックラン): 50 ETH を売却 → 上昇分の利益を確保

価格の推移:
  $3,000 →[TX1]→ $3,010 →[TX2]→ $3,040 →[TX3]→ $3,020

攻撃者の利益: (3,020 - 3,010) × 50 = $500
ユーザーの損失: 本来 $3,000 で買えたETHを $3,010-3,040 で購入

4. DEXアービトラージ

同一トークンペアの複数DEX間の価格差を利用したアービトラージです。最もポジティブなMEV活動とされ、市場効率性に貢献します。

# DEXアービトラージの基本ロジック(概念コード)

class DEXArbitrage:
    """複数DEX間の価格差を利用したアービトラージ"""

    def __init__(self):
        self.dexes = {
            "uniswap_v3": UniswapV3Client(),
            "sushiswap": SushiSwapClient(),
            "curve": CurveClient(),
        }

    def find_opportunities(self, token_pair: tuple) -> list:
        """アービトラージ機会を検索"""
        prices = {}
        for name, dex in self.dexes.items():
            prices[name] = dex.get_price(token_pair)

        opportunities = []
        for buy_dex, buy_price in prices.items():
            for sell_dex, sell_price in prices.items():
                if buy_dex != sell_dex:
                    spread = (sell_price - buy_price) / buy_price
                    if spread > self.min_spread:
                        opportunities.append({
                            "buy_dex": buy_dex,
                            "sell_dex": sell_dex,
                            "buy_price": buy_price,
                            "sell_price": sell_price,
                            "spread": spread,
                            "estimated_profit": self.calculate_profit(
                                spread, self.trade_size, gas_cost=0.005
                            )
                        })

        return sorted(opportunities, key=lambda x: x["estimated_profit"], reverse=True)

    def execute_atomic(self, opportunity: dict):
        """フラッシュローンを使ったアトミック実行"""
        # 1. フラッシュローンで資金調達
        # 2. DEX Aで購入
        # 3. DEX Bで売却
        # 4. フラッシュローンを返済 + 手数料
        # 5. 利益を確保
        # すべて1トランザクションで実行(失敗時は全体がリバート)
        pass

5. 清算(Liquidation)

レンディングプロトコルで担保率が閾値を下回ったポジションを清算し、清算報酬を獲得する戦略です。

プロトコル清算閾値清算報酬清算方式
Aave V3変動(80-90%)5-10%即時清算
Compound V3変動~5%吸収方式
MakerDAO150%13%オランダ式オークション
Morpho変動変動即時清算

MEV種類の比較

MEV種類倫理性難易度平均利益ユーザーへの影響
DEXアービトラージポジティブ$10-1,000/TX価格均一化に貢献
清算中立中〜高$50-10,000/TXプロトコルの健全性維持
バックランニング中立$10-500/TX直接的被害なし
フロントランニングネガティブ$10-1,000/TXユーザーが不利なレート
サンドイッチ攻撃ネガティブ$10-5,000/TXユーザーが直接的に損失

MEVサプライチェーン

Ethereum(PoS)におけるMEVのサプライチェーンは、PBS(Proposer-Builder Separation)によって構造化されています。

MEV-Boost アーキテクチャ

[MEV サプライチェーン]

サーチャー (Searcher)
  │ MEV機会を発見し、バンドルを作成
  │ 例: アービトラージ、清算、サンドイッチ
ビルダー (Builder)
  │ 複数のバンドルとユーザーTXを組み合わせて
  │ 最も収益性の高いブロックを構築
  │ 例: Flashbots Builder, BloXroute, Titan
リレー (Relay)
  │ ビルダーのブロックをバリデーターに仲介
  │ ブロック内容を隠蔽(MEV盗難防止)
  │ 例: Flashbots Relay, BloXroute, Ultra Sound
バリデーター (Validator/Proposer)
  │ 最も高い入札のブロックを選択・提案
  │ ブロック報酬 + MEV報酬を受取
ブロック確定

各プレイヤーの収益分配

プレイヤー役割収益源収益割合(目安)
サーチャーMEV機会の発見・実行MEV利益 - ビルダーへの入札10-30%
ビルダーブロック構築サーチャーからの手数料 - バリデーターへの入札5-15%
バリデーターブロック提案ビルダーからの入札額50-80%
リレー仲介通常無料(公共財)0%

Flashbots

Flashbots(フラッシュボッツ)は、MEVの民主化と透明化を目指すリサーチ&開発組織です。Ethereum上のMEVインフラの中核を担っています。

Flashbots の主要プロダクト

プロダクト説明対象
MEV-BoostPBS実装、バリデーター用バリデーター
Flashbots ProtectプライベートTX送信RPC一般ユーザー
Flashbots Builderブロックビルダービルダー
MEV-ShareMEV利益のユーザー還元サーチャー/ユーザー
SUAVE次世代MEVインフラ(開発中)全参加者

Flashbots Protect の使い方

[Flashbots Protect を MetaMask に追加]

ネットワーク設定:
  ネットワーク名: Flashbots Protect
  RPC URL: https://rpc.flashbots.net
  チェーンID: 1
  通貨シンボル: ETH

効果:
  ✓ トランザクションがパブリックメモリプールに公開されない
  ✓ サンドイッチ攻撃から保護
  ✓ フロントランニングから保護
  ✓ 失敗したTXのガス代が不要(リバートプロテクション)

MEV-Share: ユーザーへのMEV還元

MEV-Shareは、ユーザーのトランザクションから生じるMEV利益の一部をユーザーに還元する仕組みです。

[MEV-Share のフロー]

1. ユーザーがFlashbots Protect経由でTX送信
2. Flashbotsがトランザクションの一部情報をサーチャーに公開
   (完全な情報ではなく、ヒント情報のみ)
3. サーチャーがバックランTXを作成
4. MEV利益が発生
5. 利益の一部がユーザーに還元

利益分配:
  ユーザー: 50-90%(設定可能)
  サーチャー: 10-50%

SUAVE — 次世代MEVインフラ(構想)

SUAVE(Single Unifying Auction for Value Expression)は、Flashbotsが構想する次世代のMEVインフラです。

SUAVEの目標:
├── チェーン非依存のMEVインフラ
│   └── Ethereum, Solana, L2等すべてに対応
├── プライバシー保護
│   └── TEE(Trusted Execution Environment)の活用
├── 分散化
│   └── 単一のビルダーへの集中を排除
└── MEVの民主化
    └── 誰でもサーチャー/ビルダーに参加可能

Jito — Solana MEVインフラ

Jito(ジト)は、Solana上のMEVインフラを提供するプロトコルです。バンドルトランザクションとブロックエンジンを通じて、Solana版のFlashbotsとも言える役割を果たしています。

Jito の仕組み

[Jito MEV サプライチェーン(Solana)]

サーチャー
  │ バンドルトランザクションを作成
  │ チップ(入札)を付与
Jito Block Engine
  │ バンドルを受信・最適化
  │ バリデーターに配信
Jito-Solana バリデーター
  │ Jitoクライアント(修正版Solanaバリデーター)を実行
  │ バンドルを含むブロックを提案
ブロック確定

Jito バンドルの送信例

# Jito バンドルトランザクション送信(概念コード)
import httpx
import base58

class JitoClient:
    """Jito Block Engine クライアント"""

    BLOCK_ENGINE_URL = "https://mainnet.block-engine.jito.wtf"

    async def send_bundle(self, transactions: list, tip_lamports: int = 10000):
        """バンドルトランザクションを送信"""

        # チップトランザクションを追加
        # Jitoのチップアカウントの一つに送金
        tip_accounts = [
            "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
            "HFqU5x63VTqvQss8hp11i4bVqkfRtQ7NmXwkiNPLArUT",
            # ... 他のチップアカウント
        ]

        tip_tx = self.create_tip_transaction(
            to=random.choice(tip_accounts),
            amount=tip_lamports
        )
        transactions.append(tip_tx)

        # バンドルを送信
        serialized = [
            base58.b58encode(tx.serialize()).decode()
            for tx in transactions
        ]

        response = await httpx.AsyncClient().post(
            f"{self.BLOCK_ENGINE_URL}/api/v1/bundles",
            json={
                "jsonrpc": "2.0",
                "id": 1,
                "method": "sendBundle",
                "params": [serialized]
            }
        )

        return response.json()

    async def get_tip_floor(self) -> int:
        """現在のチップフロア(最低入札額)を取得"""
        response = await httpx.AsyncClient().post(
            f"{self.BLOCK_ENGINE_URL}/api/v1/bundles",
            json={
                "jsonrpc": "2.0",
                "id": 1,
                "method": "getTipAccounts",
                "params": []
            }
        )
        return response.json()

Jito のステーキング(JitoSOL)

指標
JitoSOL TVL$2B以上
APY約7-8%(ベースステーキング + MEV報酬)
MEV報酬割合APYの約1-2%がMEV由来
バリデーター数200以上

MEV Bot開発の基礎

開発に必要な技術スタック

レイヤー技術用途
ブロックチェーン接続WebSocket RPC, geth/rethメモリプール監視、TX送信
スマートコントラクトSolidity, Foundryアトミック実行コントラクト
バックエンドRust, Go, Python戦略ロジック、高速処理
データRedis, ClickHouse状態管理、分析
インフラ低レイテンシVPSバリデーターに近いサーバー

シンプルなアービトラージBotの構造

# MEV アービトラージBot の基本構造(概念実装)
import asyncio
from web3 import Web3
from web3.middleware import geth_poa_middleware

class SimpleArbBot:
    """DEXアービトラージの基本Bot"""

    def __init__(self, config: dict):
        self.w3 = Web3(Web3.WebsocketProvider(config["ws_url"]))
        self.account = self.w3.eth.account.from_key(config["private_key"])
        self.arb_contract = self.w3.eth.contract(
            address=config["arb_contract"],
            abi=config["arb_abi"]
        )
        self.min_profit_wei = Web3.to_wei(0.005, "ether")  # 最低利益

    async def monitor_mempool(self):
        """メモリプールを監視してMEV機会を検知"""
        async for tx_hash in self.w3.eth.subscribe("pendingTransactions"):
            try:
                tx = await self.w3.eth.get_transaction(tx_hash)
                if self.is_target_dex(tx["to"]):
                    opportunity = await self.analyze_opportunity(tx)
                    if opportunity["profitable"]:
                        await self.execute(opportunity)
            except Exception as e:
                continue

    async def analyze_opportunity(self, pending_tx: dict) -> dict:
        """保留中TXを分析してアービトラージ機会を評価"""
        # デコードして取引内容を把握
        decoded = self.decode_swap(pending_tx)

        # 価格インパクトをシミュレーション
        price_after = self.simulate_price_impact(
            decoded["pool"],
            decoded["amount"],
            decoded["direction"]
        )

        # 反対方向の取引で利益が出るか計算
        profit = self.calculate_backrun_profit(
            decoded["pool"],
            price_after,
            gas_price=pending_tx["gasPrice"]
        )

        return {
            "profitable": profit > self.min_profit_wei,
            "expected_profit": profit,
            "pending_tx": pending_tx,
            "strategy": "backrun"
        }

    async def execute(self, opportunity: dict):
        """Flashbotsバンドルとして実行"""
        bundle = [
            opportunity["pending_tx"],  # 元のTX
            self.build_backrun_tx(opportunity)  # バックランTX
        ]

        # Flashbots Relay に送信
        result = await self.flashbots.send_bundle(
            bundle,
            target_block=self.w3.eth.block_number + 1
        )

        if result["bundleHash"]:
            print(f"Bundle submitted: {result['bundleHash']}")
            print(f"Expected profit: {opportunity['expected_profit']} wei")

アトミック実行コントラクト

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@aave/v3-core/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol";

contract ArbExecutor is FlashLoanSimpleReceiverBase {
    address public owner;

    constructor(address _poolProvider)
        FlashLoanSimpleReceiverBase(IPoolAddressesProvider(_poolProvider))
    {
        owner = msg.sender;
    }

    /// @notice フラッシュローンを使ったDEXアービトラージ
    function executeArb(
        address token,
        uint256 amount,
        bytes calldata swapData
    ) external {
        require(msg.sender == owner, "Not owner");

        // Aave V3 フラッシュローン実行
        POOL.flashLoanSimple(
            address(this),
            token,
            amount,
            swapData,
            0  // referralCode
        );
    }

    /// @notice フラッシュローンのコールバック
    function executeOperation(
        address asset,
        uint256 amount,
        uint256 premium,
        address initiator,
        bytes calldata params
    ) external override returns (bool) {
        // 1. DEX Aで売却
        // 2. DEX Bで購入
        // 3. 利益確認

        (address dexA, address dexB, bytes memory swapParamsA, bytes memory swapParamsB)
            = abi.decode(params, (address, address, bytes, bytes));

        // DEX Aでスワップ
        IERC20(asset).approve(dexA, amount);
        (bool successA,) = dexA.call(swapParamsA);
        require(successA, "Swap A failed");

        // DEX Bでスワップ(戻す)
        uint256 intermediateBalance = IERC20(intermediateToken).balanceOf(address(this));
        IERC20(intermediateToken).approve(dexB, intermediateBalance);
        (bool successB,) = dexB.call(swapParamsB);
        require(successB, "Swap B failed");

        // フラッシュローン返済(元本 + 手数料)
        uint256 totalDebt = amount + premium;
        uint256 finalBalance = IERC20(asset).balanceOf(address(this));
        require(finalBalance >= totalDebt, "Not profitable");

        IERC20(asset).approve(address(POOL), totalDebt);

        // 利益をオーナーに送金
        uint256 profit = finalBalance - totalDebt;
        if (profit > 0) {
            IERC20(asset).transfer(owner, profit);
        }

        return true;
    }
}

MEV保護手段

ユーザー向けMEV保護

保護手段方法効果
Flashbots ProtectプライベートRPCを使用サンドイッチ攻撃から保護
MEV BlockerFlashbotsの代替プライベートRPCMEV利益の一部を還元
CowSwapバッチオークション方式MEVフリーの取引執行
1inch FusionリゾルバーネットワークMEV保護+最良レート
スリッページ設定許容スリッページを最小に攻撃の利益を制限
分割取引大口注文を分割価格インパクトを軽減

プロトコル設計によるMEV対策

[MEV-Resistant DEX 設計パターン]

1. バッチオークション(CowSwap方式)
   すべての注文を一定期間収集 → 一括で約定
   → 注文の順序に意味がなくなる → MEV排除

2. 暗号化メモリプール(Threshold Encryption)
   TX内容を暗号化 → ブロックに含まれた後に復号
   → サーチャーがTX内容を事前に知れない

3. オフチェーンオーダーブック(Intent-based)
   注文をオフチェーンで収集 → ソルバーが最適に実行
   → メモリプールに公開されない → MEV排除

4. タイムウェイテッドオーダー
   大口注文を時間分散して実行
   → 1回のブロックでの価格インパクトを低減

MEVの倫理的議論

MEVは「良い」のか「悪い」のか

立場主張
MEV肯定派市場効率性の向上(DEXアービトラージ)、プロトコルの健全性維持(清算)、バリデーターの収益源
MEV否定派一般ユーザーからの価値搾取(サンドイッチ)、ネットワークの混雑(ガスオークション)、中央集権化リスク
中立派MEVは不可避、適切な制度設計で悪影響を最小化し、良い側面を最大化すべき

MEVの分類

[ポジティブMEV]
├── DEXアービトラージ → 価格の均一化、市場効率性
├── 清算 → レンディングプロトコルの健全性維持
└── オラクル更新後の価格修正

[ネガティブMEV]
├── サンドイッチ攻撃 → ユーザーへの直接的損害
├── フロントランニング → 不公平な取引環境
└── タイムバンディット攻撃 → ブロックチェーンの安全性への脅威

[中立MEV]
├── バックランニング → 直接的被害なし
└── NFTミントスナイピング → 早い者勝ちの市場原理

MEV戦略の実践に向けて

初心者向けロードマップ

ステップ内容推定期間
1Solidityの基礎学習2-4週間
2DeFiプロトコルの理解(Uniswap, Aave等)2-4週間
3Foundryでのテスト・シミュレーション2-4週間
4メモリプール監視の実装1-2週間
5テストネットでのバックランBot実装2-4週間
6Flashbots統合1-2週間
7メインネットでの運用開始(小額)-

競争環境の現実

MEVは極めて競争の激しい分野です。以下の点を認識する必要があります:

  1. レイテンシ勝負 — ミリ秒単位の速度差が勝敗を分ける
  2. 資本要件 — フラッシュローンで軽減可能だが、ガス代は必要
  3. インフラコスト — 低レイテンシサーバー、専用ノードが必要
  4. 競合の技術力 — プロフェッショナルチームが多数参入
  5. 利益率の低下 — 競争激化により利益率は年々低下傾向

MEVは高度な技術力と深いDeFi理解を要求する分野ですが、ブロックチェーンの仕組みを根本から理解するための最良の学習テーマでもあります。実際に利益を上げることが目的でなくても、MEVの知識はDeFi開発者・トレーダーにとって不可欠な基盤知識です。