こんにちは、よだかです。
ここしばらく、DeFiの清算を広く追っています。
どのプロトコルで、どのような状態変化をきっかけに清算が発生するのか。その機会は第三者から事前に見えるのか。見えたとして、本当に自分の環境で取れるのか。
今回Venusを調べたのも、その流れの一つです。
最初からVenus専用の清算botを作ろうとしていたわけではありません。過去の清算を広く見ながら、「どこで清算可能状態が生まれ、実際の清算者は何をしているのか」を追っていました。
その途中で、少し変わったケースが出てきました。
保存されている状態を見る限りでは、まだ清算できません。ところが実際に清算を成功させた取引の中では、何らかの状態更新を行ったあとに清算が成立しています。
さらに掘ると、この「取引の中で清算可能状態が作られるように見えるケース」は一種類ではありませんでした。
一つは、一般の第三者でも実行できる利息状態の更新です。
もう一つは、Chainlink SVR / Atlasを介したオラクル更新でした。
今回は、この二つがどのように分かれていったのかを整理します。
-
-
🛠️開発記録#572(2026/9/17)清算エッジ探索をどうフェーズシフトするか?
続きを見る
383件の清算から、状態変化を追う
今回の基準にしたのは、Venus上で観測した30日間の清算383件です。
まず対象を絞り、実際の清算取引より前の状態を再構成しました。
ここで気になったのが、清算直前の保存済み状態では健全と判定されるのに、その直後のブロックでは清算が成功しているケースでした。
普通に保存済みの口座状態だけを見ると、清算対象としては出てきません。
しかし実際の清算取引を追うと、その中で複数の市場状態を更新したあとに清算しているものがありました。
そこで、清算者と同じアドレスや同じ取引を再現するのではなく、
「清算者ではない普通の第三者でも、同じ状態変化を起こせるのか」
を過去状態のシミュレーションで調べることにしました。

Venusでは、保存されている値と現在まで更新した値が同じとは限らない
ここでVenusの仕様を確認しました。
VenusのvTokenでは、借入利息が時間とともに経済的には蓄積していても、それが常に最新の値として保存され続けるわけではありません。
accrueInterest() が実行されると、前回の更新以降に蓄積した利息が市場の状態へ反映されます。
また、Venus公式ドキュメントでは、borrowBalanceCurrent() は利息を更新してから借入残高を計算する一方、borrowBalanceStored() は保存済みのデータを使うと説明されています。accrueInterest() 自体は、蓄積した利息を借入総額や準備金へ反映する処理です。
Venus Protocol — VToken Technical Reference
Venus Protocol — Protocol Math
今回見つかった一部のケースでは、実際に清算を成功させた側が、口座の参加市場について利息状態を更新してから清算していました。
これを過去ブロック上で第三者として再現すると、
更新前には拒否されていた清算が、更新後には成功しました。
つまり少なくともこの経路については、「すでに清算可能になった口座を見つける」だけではありません。
まだ保存状態では清算対象に見えない口座について、現在まで状態を進めたときに清算可能になるかを計算する
という見方が必要になります。

同じように見えたケースが、途中で二つに割れた
ここまでは、「清算者が取引の中で状態を更新している」という一つの現象に見えていました。
ところが、複数ケースを同じ方法で再現しようとすると結果が割れました。
一方では、一般の第三者が市場の利息状態を更新し、そのまま公式の清算経路を呼べば再現できました。
しかし別のケースでは、それだけでは清算できませんでした。
取引の内部をさらに追うと、清算より前にオラクルの新しい価格ラウンドが反映されていました。
しかも、このオラクル更新は誰でも同じように直接実行できるものではありませんでした。
第三者として同じ更新を直接呼ぶと権限で拒否されます。一方、実際に使われていた実行経路では更新が成立し、その後に清算が実行されていました。
ここで初めて、
同じ「取引内で清算可能状態が生まれるケース」に見えても、中身は別の仕組みではないか
と考えるようになりました。

もう一方はChainlink SVR / Atlasだった
オラクル更新側の経路を仕様から確認すると、ChainlinkのSmart Value Recapture(SVR)とAtlasにつながりました。
Chainlinkの公式説明では、SVRは価格更新に伴って発生する清算由来のOracle Extractable Value(OEV)を、オークションを通じて回収する仕組みです。
通常の価格配信とは別に、価格更新とそれに続く清算機会をオークションへ流し、探索者が入札します。落札された清算は価格更新と同じブロック内で実行されます。BNB Chainでは、このオークションシステムとしてAtlasが使われています。
Chainlink — Smart Value Recapture (SVR) Feeds
さらにAtlasの公式Searcher向け資料を見ると、対応プロトコルにVenusが明記されています。
参加自体も、特定業者だけに閉じられたものではありません。
現在の公式仕様では、Atlasには高reputationと低reputationのグループがあり、低reputation側でも最も競争力のある有効な入札を出せば勝つことができます。参加や高reputation setへのアクセスもpermissionlessとされています。BNB Chainではbondとして1 BNBが推奨されています。
Chainlink — SVR Searcher Onboarding: Atlas
Venus側の導入提案でも、SVRは「oracle更新に伴う清算MEVを回収すること」と「open searcher ecosystem」を前提として説明されています。
Venus Community — Venus x Chainlink SVR Integration Proposal
ここは今回かなり重要でした。
過去取引だけを見ていると、
「オラクル更新には権限が必要だから、普通の第三者には取れない」
と解釈してしまいそうになります。
しかし仕様を確認すると、そうではありません。
通常の清算botとしてオラクル更新を直接再現する経路ではないだけで、SVR / Atlasの探索者として参加する別の市場が存在します。
今回、その市場の収益性までは検証していません。
したがって、こちらは「取れない」と閉じるのではなく、別の研究候補として切り離すことにしました。
第三者でも再現できる側には、実際に利益が残った
一方、利息状態を一般の第三者でも更新できる側は、もう少し先まで検証しました。
30日分を同じ条件で洗い直すと、この仕組みに該当するケースが複数回確認できました。
さらに、後から結果を知っていることを利用しないように条件を制限し、清算直前の公開済み状態だけを使って再判定しました。
その多くは、事前条件だけでも検出できました。
固定した売却経路と過去時点の正確な清算量を使って経済性を計算すると、経済性まで解決できたケースはすべてgas後でもプラスでした。
30日合計でも正の利益が残りました。
ただし、ここは数字の見方に注意が必要でした。
利益は均等ではありません。
小さな機会が多く、一部の比較的大きなケースが全体収益の多くを占めていました。
したがって、
「一定頻度で安定して同じ利益が出る」
という種類のエッジではありません。
機会の発生にも偏りがあり、30日平均をそのまま将来の定常的な発生率として扱えるとは考えていません。
(公開記事なので、具体的な対象市場、売却経路、個別損益、検出条件はここでは伏せておきます。)
後知恵なしでも見えた。ただし、時間はほとんど残っていなかった
個別ケースをさらに掘ると、もう一つ重要なことが分かりました。
保存済みの口座状態だけを見ると、清算対象にはなっていません。
しかし直前ブロックが確定した時点の公開状態を使い、次のブロックで利息状態を更新した場合までシミュレーションすると、次のブロックで清算可能になることを予測できるケースがありました。
未来の取引内容や、清算後の状態を使ったわけではありません。
つまりこれは、少なくともケース単位では後知恵なしで予測可能でした。
ただし、実行可能になるのは実際の清算者が入ったブロックからでした。
もっと早いブロックですでに清算可能だったわけではありません。
ここで、「見えるか」と「取れるか」の距離が一気に問題になりました。
利益はある。でも、今の構成では間に合わない
そこで最後に、実装判断のための処理時間を測りました。
過去の対象群から作ったborrower集合に対して、外部RPCから必要な状態を読み、候補を検出し、清算判断まで進めます。
現在の構成では、候補検出そのものはおおむね1秒前後まで来ました。
しかし、次のブロックまでに必要な一連の判断を完了できるかを繰り返し測ると、今回の外部RPC構成では一度も期限内に処理を完了できませんでした。
しかも、このベンチマークに使ったborrower集合自体が、過去に結果が出たことを知った上で作った集合です。
本番では、より広い候補群から対象を発見する工程も必要になります。
つまり現時点で言えるのは、
「利益がない」ではありません。
「仕組みが再現できない」でもありません。
「事前に見えない」でもありません。
現在の外部RPC中心の構成では、必要な判断を期限までに完了できることを証明できなかった、というところまでです。
これはかなり違います。

だから今回は「捨てる」ではなく、一度置く
このケースは、研究としてはかなり面白い位置に残りました。
仕組みは確認できました。
第三者でも再現できました。
過去の経済性もプラスでした。
後知恵なしで次の清算機会を予測できるケースも確認できました。
それでも、現在の構成では実装しません。
理由はシンプルで、今のインフラでは期限に間に合わないからです。
ただし、これは「原理的に無理」という結論ではありません。
より近い状態を持つノード構成や、全候補を毎回ゼロから計算しない検出方法など、処理系そのものを変えれば結果が変わる可能性は残っています。
そこにどこまで開発コストを払うかは、今回確認した利益の大きさや発生分布だけでなく、同じインフラを別の研究でも使い回せるかを含めて考える必要があります。
そのため、現時点では保留にしました。
将来、別の目的で低遅延なBNB Chainの観測・計算基盤を作ることになれば、戻ってくる可能性は十分あります。
仕様を先に読んでいれば、もっと早く分けられた部分もあった
今回の振り返りとして、研究の順序にも一つ課題が残りました。
利息更新型の仕組みそのものは、実際の過去取引を再生しなければ分からない部分が大きかったです。
一方で、オラクル更新型については少し違います。
VenusへのSVR導入や、BNB ChainでAtlasが使われていること、探索者向けの参加経路が存在することは、公開資料から確認できました。
つまり清算取引を深く再生する前に、
プロトコル本体だけでなく、価格配信・OEV回収・オークションといった周辺の実行インフラまで先に監査していれば、「これは通常の清算競争とは別経路かもしれない」ともっと早く分岐できた可能性があります。
これは次の探索から取り入れます。
取引履歴だけを見るのでも、仕様書だけを見るのでも足りません。
両方を往復しながら、今見ている現象がどの層で作られているのかを確認する必要があります。
「エッジがある」と「自分が取れる」の間は、まだ遠い
今回のVenusでは、
仕組みが存在するところまで確認できました。
第三者でも再現できました。
経済性も残りました。
事前検出もできました。
それでも最後に、処理時間で止まりました。
一方で、同じように見えた別の清算を追うと、そこにはSVR / Atlasという別市場がありました。
「取れない」と思ったものが、実は参加方法の違う競争市場でした。
結局、エッジ探索で知りたいのは「利益が発生していたか」だけではありません。
どの状態変化が利益を生み、その状態変化は誰に利用でき、いつ見え、自分の観測・計算・実行がその期限までに届くのか。
この一つ一つの距離を埋めていく必要があります。
以前の[🛠️開発記録#580「エッジはどこで消えるのか」]では、エッジが観測から実行へ進む途中で消えていく話を書きました。
今回のケースは、その続きとしてかなり具体的でした。
ただ、まだ「消えた」と決めるつもりもありません。
現時点の自分の構成では届きませんでした。
今分かっているのは、そこまでです。
次に戻ってくるときは、「本気で取りにいくなら何を変える必要があるのか」を掘る段階になります。
それでは、また。