こんにちは、よだかです。
今日はDeFiアービトラージbotの執行部を整備していました。
これまでは市場の価格差を観測し、その価格差が実際の取引で利益になるのかを検証してきました。現在は、観測した候補を実際に執行するための仕組みを段階的に作っています。
今回も、実際のウォレット残高を引き継いだローカルfork環境で、資産の準備やコントラクトへの入金・回収などを試しました。
まだ本番環境で裁定取引を実行したわけではありません。実資金の移動や本番コントラクトのデプロイも行っていません。
ただ、この作業の途中で、以前使っていたメインウォレットの残高と取引履歴を確認する機会がありました。
そこで、二つの興味深い出来事を見つけました。
一つは、昔のブリッジ操作で失ったと思っていたDAIが、いつの間にか戻ってきていたこと。
もう一つは、送金した覚えのないETHの送金履歴が、大量に残っていたこと。
後者については以前からアドレスポイズニングだと考えていましたが、今回は実際のトランザクションを改めて確認しました。
調べてみると、どちらも第三者が自分のウォレットに関係するトランザクションを発行した事例でした。
しかし、実際に起きていたことは大きく異なります。
今回は、二つの取引を調べて分かったことと、そこから更新した理解を記録します。
1.執行準備の途中で古いウォレットを点検した
現在取り組んでいるのは、DEX間の価格差を検出するだけでなく、数量や費用、実行可能な時間を考慮して執行につなげる仕組みです。
過去の市場状態を使った再現試験や、トランザクション全体のシミュレーションなどを進め、ローカルfork上での署名・送信・実行結果の確認まで接続しています。
ただし、過去の状態で取引が成立したことと、今後発生する機会を実際に取得できることは別です。
実運用には、署名権限や資金管理、トランザクションの採用状況、失敗時の処理など、まだ確認すべきことが残っています。
そこで今回は、実際に保有している資産を想定した資金準備の試験を行いました。
その際、以前DeFi運用に使っていたメインウォレットを確認しました。
しばらく積極的には使用していなかったウォレットです。
残高を確認し、過去のアクティビティを見直していると、思いがけない発見がありました。

2.失ったと思っていたDAIがRainbow Bridgeから戻っていた
最初に気になったのは、身に覚えのないDAIの入金履歴でした。
送金元を確認すると、Etherscanには「Near: Rainbow Bridge」というラベルが付いていました。
Rainbow Bridgeは、EthereumとNEARの間でトークンを移動するためのブリッジです。
私は以前、このブリッジを利用していました。
実際、2022年にはEthereum上のDAIをAuroraへブリッジする手順をブログにまとめています。
当時はDeFiの利用範囲を広げるため、複数のチェーンやブリッジを試していました。
その過程で、ブリッジに失敗してDAIを失ったと思っていた記憶があります。
そのため、今回の入金履歴を見たときは、昔の未完了処理が関係しているのではないかと考えました。
さらにトランザクションを調べると、実行元には unlost.eth という名前が付いていました。
Etherscan上のラベルは「Unlost.money: Claim Relayer」です。
取引では Multicall3 の aggregate3 が呼び出され、Rainbow Bridgeから複数のアドレスへトークンが移動していました。
その中に、私のウォレットへのDAIの移動が含まれていたわけです。
つまり、少なくとも次のことが確認できました。
- Rainbow Bridgeのコントラクトから、私のウォレットへDAIが移動している。
- トランザクションを実行したのは私ではなく、Unlost.moneyのRelayerである。
- 一つのトランザクションで、複数の受取人に対する処理が行われている。
ただし、今回のDAIが、過去のどのブリッジ操作に対応するものなのかまでは確認できていません。
以前失敗したと思っていた操作との関連は有力ですが、同一のものだったと断定するには、当時のブリッジ履歴まで遡る必要があります。
それでも、自分が操作していないのに、以前のブリッジに関係する資産が実際に戻ってきたという点は確かです。
では、どうしてそんなことが可能なのでしょうか。
3.Rainbow Bridgeには第三者が出金を完了できる仕組みがある
Rainbow Bridgeの仕組みを改めて確認しました。
基本的には、Ethereum側でトークンをロックし、その証明を使ってNEAR側で対応するトークンを利用可能にする構造です。
逆方向では、NEAR側で対応するトークンを焼却し、その証明をEthereum側へ渡すことで、ロックされていた元のERC-20トークンを解除します。
Ethereum側のコントラクトには、ERC20Locker という名前が付いています。
今回確認したコントラクトの公開アドレスは次のとおりです。
0x23ddd3e3692d1861ed57ede224608875809e127f
このコントラクトには、lockToken と unlockToken という関数があります。
前者はトークンをロックするための処理、後者は証明を検証してロックされたトークンを解除するための処理です。
重要なのは、出金を完了するトランザクションの発行者が、必ずしも資産の受取人本人である必要はないという点です。
正しい証明を提示できれば、第三者が解除処理を呼び出せる設計になっています。
そして、資産は証明に記録された受取先へ送られます。
第三者が実行したからといって、その第三者が自由に受取人を変更できるわけではありません。

この仕組みを利用しているのが、今回見つけたUnlost.moneyというプロジェクトです。
公式サイトによると、Unlost.moneyは古いDeFiコントラクトや取引所、ブリッジなどに残された未請求資産を調べ、所有者が回収できるようにする活動を行っています。
資産の照会は無料で、ウォレット接続も必要ありません。
そして、一部のコントラクトでは、第三者が請求処理を実行しても資産が本来の所有者へ直接送られるため、Unlost.money側がガス代を負担して回収を進めていると説明されています。
今回のトランザクションも、こうした第三者による出金完了処理だったと考えられます。
資産を返しても実行者が利益を得るわけではない
ここでもう一つ気になったのが、Unlost.moneyの活動目的です。
ガス代を自分たちで負担し、第三者の資産を回収しても、資産そのものは元の所有者へ送られます。
通常の裁定取引のように、価格差から利益を得る構造ではありません。
公式サイトには任意の謝礼についての説明がありますが、支払いは義務ではありません。
開発に関わる人物も、Xへの投稿で、AIを用いてコントラクトに残された資産を自動回収する活動を、慈善的な取り組みとして紹介しています。
実際の運営費や謝礼による収入は不明ですが、少なくとも第三者の未請求資産を回収するために、自ら費用を負担しているというのは興味深い活動です。
今回の件を通じて、ブリッジの処理が途中で止まっていたとしても、それが必ずしも資産の永久的な消失を意味するわけではないと分かりました。
もちろん、すべてのブリッジで同じことができるわけではありません。
資産が失われた原因やコントラクトの仕様によって、回収可能性は変わります。
ただ、「操作が完了していないこと」と「資産の回収可能性がなくなったこと」は別の状態です。
以前はGOXしたと思っていた資産について、今回この違いを実感することになりました。
4.送っていないETHの履歴は偽のERC-20イベントだった
もう一つの発見は、不審なETHの送金履歴です。
このウォレットには、以前から覚えのない送金アクティビティが大量に残っていました。
発生したのは、私がCEXのサブアカウントへ資産を送金した直後です。
同じような数量のETHを、同じようなアドレスへ何度も送ったことになっていました。
しかし、そんな操作をした覚えはありません。
そして、実際のETH残高も減っていませんでした。
さらに、表示されている送金先アドレスは、実際に使ったCEXの入金アドレスと先頭・末尾が似ていました。
当時からアドレスポイズニングという攻撃手法は知っていたので、これは偽装された履歴だろうと判断して無視していました。
今回、改めてEtherscanでトランザクションの詳細を確認しました。
すると、実際のトランザクション発行者は私のウォレットではなく、別のアドレスでした。
呼び出し先のコントラクトにもフィッシング関連の警告が付いています。
また、確認したトランザクションでは、直接のETH送金額を表す Value は 0 ETH でした。
一方、ERC-20トークンの移動履歴には、私のアドレスを送信元とした、ETH送金に見える記録が存在していました。
ただし、これは本物のETHの送金ではありません。
悪意あるコントラクトが作成した、偽のトークン移動イベントだったのです。
5.アドレスポイズニングは送金先の取り違えを狙う
ここで、今回使われていた仕組みを整理します。
まず、Ethereum上のDAIやUSDCなどのERC-20トークンは、スマートコントラクトによって管理されています。
例えば、AさんからBさんへ10 DAIを送金した場合、DAIのスマートコントラクトがAさんの残高を減らし、Bさんの残高を増やします。
そして、この資産移転を記録するために、コントラクトは Transfer というイベントを発行します。
このイベントには、次の3つの情報が含まれています。
Transfer(from, to, value)
from:送信元アドレスto:送信先アドレスvalue:移転したトークンの数量(最小単位で記録)
ウォレットやブロックエクスプローラーは、こうしたイベントログを参照してトークンの移動履歴を表示します。
ところが、ここに問題があります。
Transfer イベントが記録されていることと、実際に資産が移動したことは、必ずしも同じではありません。
なぜなら、イベントはスマートコントラクトが発行する記録であり、イベントの発行自体が残高の変更を保証するわけではないからです。
例えば、攻撃者が自分で作成したトークンコントラクトなら、実際には残高を変更せず、任意のアドレスを送信元とする Transfer イベントだけを発行できます。
この場合、送信元として指定されたウォレットの所有者が、トランザクションに署名する必要はありません。
重要なのは、攻撃者が本物のETHや正規のDAIを操作できるようになったわけではないという点です。
また、攻撃者が正規のDAIコントラクトになりすまして、そのコントラクトからイベントを発行できるわけでもありません。
あくまで、自分が管理する偽のトークンコントラクトから、資産移転が行われたように見えるイベントを発行しているのです。
さらに、偽トークンの名前やシンボルを「ETH」などに設定すれば、ウォレット側の表示方法によっては、本物のETH送金と紛らわしい履歴を作ることもできます。
なお、通常のETHはERC-20トークンではありません。今回利用されていたのは、ETHに見える偽トークンのイベントです。
今回のアドレスポイズニングでは、これに送金先アドレスの偽装が組み合わされていました。
私は以前、CEXのサブアカウントへ実際に資産を送金しました。
すると、その直後から、実際の送金先と先頭・末尾が似た別のアドレスに対する送金履歴が、大量に現れました。
攻撃者は、利用者が過去の送金履歴を参照した際に、この偽のアドレスを本物の送金先と取り違えることを狙っていたと考えられます。

この図は、正規のCEX入金先への送金後、攻撃者が先頭・末尾の似たアドレスを用意し、偽トークンの Transfer イベントを発行する流れです。このケースでは、ウォレットには送金履歴が表示される一方、実際のETH残高は減っていません。
なお、攻撃者はこうした偽のイベントをブロックチェーンへ記録するために、実際にガス代を負担しています。
今回確認したトランザクションでも、複数の偽装イベントがまとめて処理されていました。
複数件を一括実行すれば、トランザクションごとの固定的なガス消費を分散できます。
攻撃が成功するかは分かりませんが、少数の利用者が送金先を取り違えるだけで、攻撃費用を回収できる可能性があります。
つまり、今回の大量の履歴汚染は、単なる嫌がらせではなく、費用を払ってでも実施する経済的な動機のある攻撃だと考えられます。
このような手口は、Etherscanの公式解説でも紹介されています。
アドレスポイズニング自体は以前から知っていましたが、実際のトランザクションを確認すると、攻撃者が何をしているのかが具体的に分かりました。
特に重要だったのは、トランザクションを実際に発行したアドレスと、Transfer イベントに記録された送信元アドレスは、必ずしも一致しないという点です。
今回の事例でも、トランザクションを発行したのは第三者でしたが、イベント上の送信元には私のウォレットが指定されていました。
そのため、ウォレットには私が送金したような履歴が表示されていたわけです。
しかし、実際のETH残高は変化していませんでした。
ウォレットに表示された履歴だけでは、誰が操作し、どの資産が実際に移動したのかまでは判断できないということです。
6.オンチェーンの記録と実際の資産移転は同じではない
今回の二つの事象を並べると、興味深い違いが見えてきます。
DAIの返還では、第三者が正当な請求処理を実行し、実際に資産が移動していました。
一方、アドレスポイズニングでは、第三者が偽のイベントを発行し、資産が移動したように見える履歴を作っていました。
どちらも、ウォレット所有者本人が操作していないところで発生しています。
しかし、技術的な意味はまったく異なります。

ここで重要なのは、イベントログそのものが無意味だということではありません。
ブロックチェーンにイベントが記録されたこと自体は事実です。
ただし、そのイベントを発行したコントラクトが何者なのか、イベントが示す内容が実際の資産移転と対応しているのかは、別途確認する必要があります。
例えば、ERC-20の Transfer イベントを調べる場合でも、正規トークンのコントラクトが発行したものなのか、名前だけを似せた別のコントラクトが発行したものなのかで意味が変わります。
また、トランザクションの送信者と、イベント内に記録された送信元アドレスも同じとは限りません。
これらを混同すると、存在しない送金を実際の資産移転として解釈してしまう可能性があります。
以前、清算後の担保がどのように移動するのかを調べた際にも、トランザクションのreceiptやイベントログを使って、実際の資産移動を追跡しました。
関連記事:🛠️開発記録#567(2026/9/11) 清算後の資産移動をオンチェーンから追う|研究工程を細かく刻みすぎた話
今回も、考え方は同じです。
「履歴に表示されている」という事実から、「何が実際に行われたのか」まで進むには、もう一段階の確認が必要でした。
具体的には、トランザクションの送信者、呼び出されたコントラクト、イベントの発行元、正規資産の残高変化などを照合する必要があります。
これは今回進めているbotの執行部でも重要な考え方です。
実行されたように見えることと、想定した資産移転が実際に成立したことを、同じものとして扱ってはいけません。
7.知っていた仕組みを実際の取引から理解し直した
今回の調査では、AIも使いながらEtherscanのトランザクション情報を整理しました。
以前であれば、個々のトランザクションを一つずつ確認しながら、「これは怪しいのではないか」と判断していたと思います。
今回は、送信者、呼び出し先、イベント、トークンの種類などを照合し、実際に起きた処理を整理することができました。
もちろん、AIによる説明だけでオンチェーンの検証が完了するわけではありません。
今回も、Etherscanの取引情報や公開されているコントラクトの仕様を参照した分析であり、すべての処理をノードから独立に取得して検証したわけではありません。
特にDAIの返還については、過去のどのブリッジ操作に対応しているのかという点が残っています。
それでも、以前から知っていた攻撃の仕組みと、今回初めて知った未請求資産の回収処理について、具体的なオンチェーン事例を通じて理解を深めることができました。
アドレスポイズニングについては、当時すでに偽装だと判断していました。
今回は、その判断をトランザクションの構造から説明できるようになりました。
一方、Rainbow Bridgeについては、昔失敗したと思っていた処理が、第三者の実行によって完了する可能性があることを知りました。
そして、どちらのケースでも、第三者は自分のガス代を使ってトランザクションを実行していました。
一方は所有者へ資産を戻し、もう一方は所有者を誤送金へ誘導する。
同じEthereum上で、こうした異なる目的の処理が行われているわけです。
今回の一番大きな学びは、トランザクションが記録されているという事実だけでは、その意味まで理解したことにはならないという点だったと思います。
どのコントラクトが、どのような条件で、何を実行し、その結果どの資産が移動したのか。
そこまで確認して、初めて実際に起きたことを説明できます。
今日の本来の作業はアービトラージbotの執行準備でした。
その途中で、昔のウォレットから思いがけず二つの技術的な事例を発見することになりました。
予定していた研究とは別のところで、オンチェーンの仕組みについて理解を更新できた一日です。
参考・一次情報
今回の調査で参照した主な資料です。
- Unlost.money 公式サイト
未請求資産の探索、第三者による請求処理、任意の謝礼についての説明。 - Rainbow Bridge:ERC-20/NEP-141 Token Connector(Near-One公式GitHub)
Ethereum側のロックと解除、NEAR側の処理、証明の検証に関する仕様。 - Rainbow Bridge ERC20Locker(Etherscan)
Ethereum上の検証済みコントラクト、lockToken・unlockTokenなどの実装。 - Etherscan:Address Poisoning Attacks
アドレス偽装、トークン偽装、イベント偽装の仕組み。 - EIP-20:ERC-20 Token Standard
ERC-20のTransferイベントおよび関連関数の正式な仕様。 - DiscusFishによるUnlost.moneyの活動紹介(X)
AIを利用した未請求資産の自動回収についての発信。
※個人ウォレットを特定できる情報を避けるため、今回の個別トランザクションハッシュ、正確な返還数量、個人アドレスなどは掲載していません。