Cardano の DEX、Splash は、9 月 13 日に ADA/OADA の StableSwap プールから約 242 万 ADA と約 199 万 OADA が持ち出された件について、原因と資金の行方をまとめた 8 ページの調査報告を公開しました。原因は 2024 年に監査を受けた範囲のコードにあり、計算の途中で残高がマイナスになっても取引を拒まない作りだったと、報告書は結論づけています。
今朝は Signal で Optim Finance の停止告知を、Daily Intel で報告書の要点をお伝えしました。この記事では報告書を章ごとに読み、攻撃の手順、監査との関係、資金の追跡の方法、OADA の再開を難しくしている事情を順に整理します。
■ 45 秒の間隔で送られた 2 本の取引
報告書によると、流出は協定世界時 9 月 13 日 0 時 47 分から 48 分(日本時間 9 時 47 分から 48 分)にかけて、同じ人物による 2 本の取引で行われました。2 本の間隔は 45 秒です。攻撃者のアドレスは同じ日の協定世界時 0 時 30 分に初めて資金を受け取った新しいもので、1 本目の 26 秒前には Optim の OADA コントラクトで 100 ADA を 100 OADA に替えています。9 月 5 日以降、このプールに対するメインネット上の試しの取引はなかったとされています。
1 本目(取引 A)で、攻撃者はプールに 9,870 ADA とごく少量の OADA を入れました。ただし入れた ADA のほとんどは「プロトコル手数料」として記録され、プールの手数料の記録は 0 から 9,869.999999 ADA に増えています。取引に使える ADA の残高が増えたのは、1 lovelace(100 万分の 1 ADA)だけでした。
2 本目(取引 B)で、プールから 2,434,648.42 ADA と 1,988,222.18 OADA が引き出されました。自分で入れた 9,870 ADA とネットワーク手数料を差し引くと、攻撃者の手元に残った ADA は約 242 万 ADA です。報告書が示すプールの状態は次のとおりです。
- 取引 A の前: 実際の ADA 2,424,788.42/OADA 3,430,000.06/手数料の記録 0
- 取引 A の後: 実際の ADA 2,434,658.42/手数料の記録 9,869.999999 ADA/取引に使える ADA 2,424,788.42
- 取引 B の後: 実際の ADA 10/OADA 1,441,777.88/取引に使える ADA −9,859.999999
どちらの取引もチェーン上では検証を通った取引として記録され、LP トークンの量も、新たな発行や焼却もありませんでした。プールは形の上では壊れておらず、中身だけが抜かれた状態です。
■ 手数料の記録と残高の引き算に、確認がなかった
このプールの検証スクリプトは、実際の残高から積み上がったプロトコル手数料を差し引き、その値を取引に使える残高として StableSwap の計算式に入れていました。報告書は、この流れの中で 3 つの確認が欠けていたと指摘しています。
- 差し引いた残高がプラスであること、手数料が残高を超えないことを、取引の前後どちらでも確かめていない。台帳そのものはマイナスの残高を持てませんが、計算の途中でマイナスの整数を扱うことは Plutus では問題なく許されます
- 手数料の記録が増える量に、下限しか設けていない。このプールは手数料の設定値が 0 だったため、0 以上の増加であれば何でも通り、入れた ADA のほぼ全額を手数料として申告できました
- 取引の向きを確かめていない。片方の資産が入って片方が出るという条件がなく、両方の資産が同時に減る動きも拒まれませんでした
StableSwap の計算式は、取引の前後で式の値がプラスかマイナスかを見て、プールの価値が守られているかを判定します。この判定は、両方の残高がプラスであることを前提にしています。残高の片方がマイナスになると掛け算の符号が反転し、プールが両方の資産を失うような、経済的にありえない動きでも判定を通ってしまいます。取引 A で手数料の記録を膨らませ、取引 B で取引に使える ADA をマイナスまで引き出す。2 本の取引は、この前提の外側を順に突いたものでした。
報告書は、チェーン上の数値を使って検証の計算を再現しています。残高がプラスかを確かめる仕組みがあれば取引 B が、手数料の増加に上限を設ける仕組みがあれば取引 A が拒まれ、どちらか一方だけで今回の攻撃は止まったとしています。
■ 監査の範囲内で、指摘の外にあった部分
報告書が紙幅を割いているのは、実際に動いていたコードの特定です。チェーン上のスクリプト(Plutus V2・3,177 バイト)を、splash-core リポジトリのコミット 0d28fe4 から Aiken v1.0.24-alpha でビルドし直し、ハッシュとバイト列が完全に一致することを確かめています。前後のコミットや Aiken 1.0.26 では別の成果物になるため、動いていたコードはこの 1 つに絞り込めた、という説明です。
そのうえで監査との関係を整理しています。Anastasia Labs の StableSwap 監査報告(v1.0・2024 年 8 月 5 日付、監査期間は 2024 年 6 月 7 日から 7 月 19 日)は、今回のプールの計算を含む 5 つのファイルを対象にしていました。報告書によると、監査対象のコミットから実際に動いていたコミットまでの間に、検証スクリプトが変わったのは 2 か所だけで、取引 A と B が通った交換の処理は監査の後も変わっていません。
監査の指摘は 8 件で、重大度の高い順に critical 1 件・major 1 件・medium 2 件・minor 2 件・参考情報 2 件です。6 件が解決済み、2 件が認識済みとされています。報告書は、このうち手数料の積み上げ、取引に使える残高の符号、取引の向きを扱ったものは 1 件もなかったと書いています。
監査はコードを読む作業であると同時に、どの性質を確かめたかを列挙する作業でもあります。今回の穴は、監査の対象ファイルに含まれながら、確かめた性質の一覧には入っていなかった場所にありました。利用者の側から見れば、監査報告の有無に加えて、指摘の一覧が何を扱い、何を扱っていないかまで読むと、そのプールが前提にしている条件が見えてきます。
コードを確かめる人向けの注意も 1 つあります。splash-core の main ブランチにある新しい validators_v2 のプールのコードは、今回のプールが実際に動かしていたものではありません。動いていたのは stable-swap-audit ブランチ側のファイルだと、報告書は明記しています。
■ 約 255 万 ADA の行き先と、取引所の名前を付ける基準
報告書によると、攻撃者のアドレスからは OADA の売却で得た分も含めて合計 2,552,176.54 ADA が 6 つの入金アドレスへ送られました。6 つのうち 5 つは新しいアドレスです。送られた ADA は、取引 B から 82 分以内に 4 つのカストディ型のまとまりへ集められています。内訳は KuCoin に 786,851.54 ADA、Gate.io に 550,000 ADA、運営者を確認できていない 2 つのまとまりに合わせて 1,215,325 ADA です。
報告書は、取引所の名前を付ける基準をはっきり書いています。名前を付けるのは、DefiLlama の取引所ウォレット一覧と、参加者が取引所の通常の入金手順で追跡用トークンを入れて行き先を記録した BEACNpool/ABCDE のデータセットという、独立した 2 つの公開データの両方に同じ取引所名で載っている場合か、そうしたウォレットとの間に取引所の通常の集約と同じ形の送金がチェーン上で確認できる場合に限っています。KuCoin も Gate.io も準備金証明のページで Cardano のアドレスを公表していないため、報告書のどのラベルも取引所自身が公表したものではありません。
攻撃の元手になった 12,186 ADA は、攻撃の 17 分前に KuCoin の出金用ウォレットから引き出されていました。さらに、KuCoin 側の入金アドレスの 1 つは 9 月 9 日にも使われており、6 回で合計 1,257,453 ADA を受け取っています。取引所は入金アドレスを口座ごとに割り当てるのが通例のため、同じ口座である可能性が高いとしつつ、その資金が攻撃者自身のものかどうかは確認できていないと書いています。
協定世界時 13 日 16 時 20 分(日本時間 14 日 1 時 20 分)時点では、Gate.io の 550,000 ADA と、運営者未確認のまとまりの 665,325 ADA は動いていません。一方で KuCoin 側では、協定世界時 13 日 7 時 4 分に 302,571.20 ADA が第三者のウォレットへ出金されています。取引所のホットウォレットは顧客の資金をまとめて扱うため、それが誰の出金かはチェーンのデータだけでは言えず、KuCoin に問うべき点だと報告書は整理しています。
Splash は今後、各取引所に取引 ID を添えて連絡し、残る集約先の運営者も特定したうえで、別の報告書を出すとしています。攻撃者が Splash のチームへ直接資金を返した場合は、ホワイトハットとしての解決として扱い、相応の報奨を出すとも書いています。
■ Minswap に残った約 176 万 OADA が、再開を難しくしている
持ち出された OADA のほうは、ほとんど換金されていません。攻撃者は約 199 万 OADA を Minswap V2 で FLDT に替え、それを ADA に替えましたが、得たのは 115,323.33 ADA でした。流動性の薄い OADA/FLDT プールに大量の OADA が流れ込み、プールの中身は 132,317 OADA/601,150 FLDT から 2,120,639 OADA/38,077 FLDT に変わっています。
協定世界時 13 日 14 時 53 分の時点で、このプールには 1,763,923 OADA が 45,751 FLDT に対して残り、そこから計算される OADA の価格は本来の連動水準を大きく下回っています。報告書によると、OADA にはプロトコルとしての償還の仕組みがなく、Splash・SundaeSwap・Minswap にあった他の OADA の取引の場も、ほとんど空に近い状態です。
報告書は、新たに ADA/OADA の流動性を出せば、この安値の OADA との価格差を狙った取引の相手になると書いています。修正したスクリプトを出すことと、OADA の連動を立て直すことは、別々の課題として残ります。市場に安く残る OADA をどう扱うかが決まらない限り、プールを開け直しても流動性はすぐに抜かれてしまうからです。流出したプール自体も、取引に使える ADA の残高がマイナスのまま、通常の取引ができない状態にあります。
■ 報告書で確かめられる 3 つの場所
報告書は、読者が同じ手順で確かめられるように、アドレスと取引をすべて Cexplorer にリンクしています。追加の発表を読むときに照らし合わせたいのは、次の 3 か所です。
- 第 3 章: 取引 A と B の数値と、確認を 1 つ足せば拒まれることの再計算。修正版のスクリプトが公開されたら、欠けていた 3 つの確認のどれが入ったかをここと突き合わせられます
- 第 4 章と、Splash のドキュメントに載っている Anastasia Labs の監査報告。指摘 8 件の中身と、今回の穴がどの確認の外にあったかを並べて読めます
- 第 6.4 節: KuCoin と Gate.io の名前を付けた根拠と、名前を付けていない 2 つのまとまりの扱い。取引所や集約先の運営者から公表が出たとき、報告書の見立てと一致するかをここで確かめられます
数値を公開データで再現できる形にし、取引所の名前は根拠が 2 つそろうまで付けない。報告書のこの書き方は、資金が戻るかどうかとは別に、DeFi のインシデントを記録する手本の 1 つになりそうです。
■ ことば
- StableSwap: 価格がほぼ同じになるはずの 2 つの資産の交換に向けた AMM の計算方式です。価格の近い範囲で滑りを小さくできる反面、今回のように計算式の前提が崩れると、判定そのものが意味を失います。
- 検証スクリプト(バリデーター): Cardano のスマートコントラクトで、取引を認めるかどうかを判定するプログラムです。今回は、残高の符号と手数料の増え方を確かめる条件がこのプログラムに入っていなかったことが原因とされています。
- 入金アドレスと集約: 取引所は利用者ごとに入金アドレスを割り当て、届いた資金を自社のウォレットにまとめます。報告書はこのまとめ方の特徴から、資金がどの取引所に入ったかを推定しています。
一次ソース / 関連リンク
- Splash「Splash StableSwap (ADA/OADA) exploit: incident report and funds trace」(調査報告 PDF・2026 年 9 月 13 日)
https://github.com/splashprotocol/splash-core/blob/main/validators_v2/validators/stable_pool/SPLASH_STABLESWAP_INCIDENT_2026-09-13.pdf - Splash 公式アカウントの告知(流出の発生・他の種類のプールは影響なし・報告書の公開)
https://x.com/splashprotocol/status/2099216297913377253 - Splash ドキュメント「Audits」(Anastasia Labs の StableSwap 監査報告を含む監査一覧)
https://docs.splash.trade/concepts/audits - splash-core リポジトリ(GitHub)
https://github.com/splashprotocol/splash-core - Optim Finance 公式アカウントの告知(Splash のプール悪用・プロトコル停止)
https://x.com/OptimFi/status/2099029810626593147 - SIPO の既報:Optim Finance、Splash のプール悪用で OADA を停止
https://sipo.tokyo/signal-20260914-27c54c37/ - SIPO の既報:Daily Intel 9/14
https://sipo.tokyo/daily-intel-20260914/
