メインコンテンツまでスキップ

Move VM のメモリ安全性 vs EVM のリエントランシー:Aptos と Sui のリソースモデルがスマートコントラクトの脆弱性を根本から排除する理由

· 約 14 分
Dora Noda
Software Engineer

2016 年の The DAO ハックでは、わずか 1 日の午後に Ethereum から 6,000 万ドルが流出しました。9 年経った今でも、リエントランシー攻撃は 2024 年だけで 22 件の個別事案を通じて DeFi プロトコルに 3,570 万ドルの損害を与えています。攻撃者がコントラクトの状態が更新される前に再度呼び出すという、同じ種類の脆弱性が、長年の開発者教育、監査ツール、実績のあるパターンの普及にもかかわらず、依然として EVM エコシステムを悩ませ続けています。

Move 言語をベースに構築された Aptos と Sui は、根本的に異なるアプローチを採用しています。設計段階で特定のカテゴリの脆弱性を発生不可能にしているのです。

根本的な原因:EVM のリエントランシーはどのように発生するか

Move がなぜ異なるのかを理解するには、そもそも Ethereum でなぜリエントランシーが可能なのかを正確に把握することが役立ちます。

Solidity コントラクトは、実行中に外部コントラクトを呼び出すことができます。コントラクト A がコントラクト B を呼び出すと、実行権限は完全に B に移ります。B は A が内部状態の更新を終える前に、A を再度呼び出す(「リエントリー」する)ことができます。もし A の出金ロジックが以下のようになっている場合:

// 脆弱なパターン
function withdraw(uint amount) external {
require(balances[msg.sender] >= amount);
(bool success, ) = msg.sender.call{value: amount}(""); // 最初に外部呼び出し
balances[msg.sender] -= amount; // 次に状態更新
}

攻撃者のコントラクトはコールバックで ETH を受け取り、即座に withdraw を再度呼び出すことで、balances[msg.sender] が減額される前に資金を引き出すことができます。これはまさに The DAO で起こったことです。攻撃者のコントラクトは、ループ内で出金関数を 360 万回再帰的に呼び出しました。

修正は単純に聞こえます。外部呼び出しを行う前に状態を更新することです(「Checks-Effects-Interactions」パターン)。しかし、開発者は忘れ、監査人は見落とします。このパターンは人間の勤勉さによってのみ強制される慣習であり、言語自体によって強制されるものではありません。

Move のアプローチ:リソースは複製も破棄もできない

Move は、型システムのレベルでこの種の誤りを防ぐようにゼロから設計されました。中心となる概念は、線形型システム(linear type system)リソース型(resource types) です。

Move において、リソースは以下のような特殊な値です:

  • コピーできない — ストレージの場所間を移動することしかできません。
  • 破棄できない — 明示的に消費されるか、どこかに保存される必要があります。
  • 常に単一の所有者が存在する — マッピングではなく、VM によって追跡されます。

これは抽象的に聞こえますが、その影響は具体的です。トークン転送の仕組みを考えてみましょう:

  • Solidity では、トークン残高はマッピング内の uint256 です。更新順序が間違っていれば、理論上その数値を操作できます。
  • Move では、トークンはアカウントのストレージに存在する実際のリソースオブジェクトです。物理的にある場所から別の場所へと移動させます。リソースが 2 つの場所に存在したり、どこにも存在しなかったりする中間状態はありません。

Move VM は、ソースレベルではなくバイトコードレベルでこれらの不変条件を強制します。たとえ開発者がバグのあるコードを書いたとしても、リソースを複製したり密かに破棄しようとしたりするトランザクションは、VM によって拒否されます。

なぜ Move ではリエントランシーが構造的に不可能なのか

リエントランシーには 2 つの条件が必要です。実行中に外部コードを呼び出す機能と、そのコールバック中に操作可能な変更可能な共有状態です。Move はその両方を遮断します。

Move は Solidity のような動的ディスパッチを許可しません。未知のコードに制御を渡すような任意の外部呼び出しは存在しません。関数は静的に呼び出される必要があり、呼び出し先はコンパイル時に既知です。つまり、攻撃者はコールバック中にあなたのモジュールにリエントリーするようなコントラクトをデプロイすることはできません。なぜなら、あなたのモジュールは未知の外部コントラクトに実行権限を渡すことがないからです。

さらに、Sui と Aptos の Move オブジェクトモデルは、オブジェクトが関数の内外に明示的に渡される所有権システムを使用しています。関数に「移動(move)された」オブジェクトは、その関数がオブジェクトを返すまで、他の場所からはアクセスできません。単一のトランザクション内で同じリソースに同時にアクセスすることは、単純に不可能です。

2025 年に発表された研究では、「Move では動的なコールバックが不可能なため、リエントランシーは不可能です。これは、リエントランシーが依然として大きな脅威である Solidity との根本的な違いです」と確認されています。

ミューテックスロックなしの二重支払い防止

EVM ベースのシステムでは、二重支払いの保護は慎重なプログラミングに依存しています。開発者は、状態の更新を勤勉に追跡することで、1 つのトランザクションでトークンが 2 回使われないように手動で確認する必要があります。

Move の線形型システムは、二重支払いを構造的に不可能にします。リソースはコピーできないため、コインを使うことは文字通りアカウントのストレージからそれを削除することを意味します。最初の支払いの後、そのリソースはもはやあなたの管理下に存在しないため、同じトランザクションで同じリソースを 2 回使う方法はありません。これは VM によって強制されます。慣習ではなく、制約なのです。

これは Sui の Capability オブジェクトにも適用されます。Capability リソースは、一度消費されると再度使用することはできません。これを、Capability が通常 boolean やアドレスマッピングにエンコードされたロールであり、何度もチェックできる EVM のアクセス制御パターンと比較してみてください。

Sui での実際の事例では、ある DEX で、出金ロジックが Capability そのものではなく、Capability への 変更可能な参照 に対して単一使用の制約を強制し損ねたという欠陥が見つかりました。これは、Move のリソースモデルが多くのバグを排除する一方で、所有されたリソースではなく参照を扱う場合には依然としてロジックエラーが発生する可能性があることを示しています。脅威の範囲は劇的に狭まりましたが、ゼロになったわけではありません。

整数オーバーフロー:Move がデフォルトで解決するもう一つの問題

初期の Solidity(0.8.0 未満)では、整数の算術演算においてオーバーフローが発生しても、警告なしに値がラップアラウンドしていました。これにより、攻撃者がオーバーフロー条件を誘発してトークン残高を操作することが可能となり、この脆弱性はいくつかの有名な DeFi エクスプロイトの原因となりました。

Solidity 0.8.0 では自動オーバーフローチェックが導入されましたが、それは何年もの被害が出た後のことでした。Move は当初からこの保護機能を備えています。整数オーバーフローを引き起こすすべてのトランザクションは、自動的に中止(abort)されます。オプトアウトする方法や、デフォルトの unchecked に相当する機能はなく、古い動作をするレガシーコントラクトを心配する必要もありません。

形式検証:Move Prover vs. EVM オーディット

Move のセキュリティストーリーは、言語そのものだけでなく、そのツールセットにも及びます。Move Prover は、言語自体と並行して構築された形式検証ツールであり、後付けのものではありません。

Move Prover を使用すると、開発者は仕様記述言語を用いて、Move ソースファイル内に直接仕様(specification)を記述できます。これらの仕様は、実装に対して数学的に検証されます。たとえば、「この関数が実行された後、コインの総供給量は変わらない」といった仕様を宣言できます。Prover は、これが常に真であることを確認するか、失敗するケースを具体的に示す反例(counterexample)を提供します。

これは、ほとんどの Solidity オーディット(監査)の手法とは根本的に異なります。

項目Move ProverSolidity オーディットツール
検証タイプ数学的証明パターンマッチング / ファジング
カバレッジ完全(仕様の範囲内)ベストエフォート(最善努力)
統合言語ツールチェーンの一部サードパーティツール(Slither, Certora)
タイミング開発時デプロイ前のオーディット
コスト無料、リポジトリ内高額な手動オーディット

Solidity 用の Slither のようなツールは、静的解析を行い、既知の脆弱性パターンを検出します。Solidity 用の Certora Prover は形式検証をサポートしており、トランザクションをまたぐ不変条件を含む、より広範なプロパティを表現できます。しかし、Certora は別の言語で仕様を記述し、別のパイプラインを実行する必要があるため、日常的な開発ツールというよりも、専門的なオーディット工程としての側面が強いです。

Move Prover の緊密な統合により、Aptos や Sui の開発者は、高価なオーディットの段階を待つことなく、開発中にローカルで形式検証を実行できます。Aptos フレームワーク自体も、標準ライブラリ用に Move Prover の仕様を同梱して提供しており、アプリケーション開発者が継承できるセキュリティのベースラインを構築しています。

残留リスク:Move が排除できないもの

Move の設計は、万能なセキュリティ保証ではありません。Move コントラクトの実際のオーディットでは、開発者が依然として以下の問題を混入させる可能性があることが明らかになっています。

  • ビジネスルールにおける ロジックエラー(最も一般的なカテゴリ)
  • 所有リソースの代わりに可変参照(mutable references)を使用した場合の アクセス制御のバグ
  • DeFi プロトコルにおける 経済的設計の欠陥(価格オラクルの操作、フラッシュローン攻撃)
  • 複数のモジュールが予期しない方法で相互作用した際の クロスモジュール相互作用のバグ

2024 年の調査で 652 個の Move コントラクトを手動で監査したところ、8 種類の欠陥タイプが特定され、その半分はそれまで報告されていなかったものでした。攻撃対象領域は Solidity よりも小さいものの、依然として存在しています。

Aptos や Sui における最善のセキュリティ体制は、言語に組み込まれた保護機能だけに頼るのではなく、Move Prover による仕様定義、サードパーティによるオーディット、そして経済的セキュリティ分析を組み合わせることです。

2025 年の DeFi ビルダーにとってこれが重要な理由

数字が如実に物語っています。2024 年、スマートコントラクトの脆弱性により、DeFi セクターは 14 億ドル以上の損失を被りました。そのうちリエントランシーによる被害は 3,570 万ドルに上りました。これは、同等の TVL(預かり資産)を持つ Move ベースのチェーンであれば、構造的にゼロに抑えられたはずのカテゴリです。

金融アプリケーションを構築する開発者にとって、VM(仮想マシン)の選択は、実質的にデフォルトの脅威モデルの選択を意味します。EVM で構築するということは、必須の規律として「Checks-Effects-Interactions(確認・実行・相互作用)」パターンを採用することを意味します。一方、Move で構築するということは、リエントランシーがそもそも脅威モデルに含まれないことを意味します。チームは、セキュリティに関するリソースをロジックエラーや経済的設計に集中させることができます。

これは小さな違いではありません。脅威の対象領域が狭いほど、形式検証ツールはより効果的に機能します。オーディット担当者は、既知の脆弱性クラスに時間を費やす必要がなくなるため、より深い分析が可能になります。言語がクリティカルな不変条件を自動的に強制することで、正しいコードを書く際の手間(認知的負荷)が軽減されます。

インフラストラクチャ・レイヤー

セキュリティの保証は、開発者が実際にこれらのチェーン上で大規模に構築できてこそ意味を持ちます。ネットワークにアクセスするために独自の Aptos または Sui ノードを運用するには、ハードウェアのプロビジョニング、ソフトウェアのアップグレード、監視、インシデント対応など、多大な運用コストがかかります。

BlockEden.xyz は、Aptos と Sui 向けにエンタープライズグレードの API アクセスを提供しています。開発者は、ノードインフラを管理することなく、Move のセキュリティ保証を活用して構築に専念できます。当社のサービスを探索して、より安全な Web3 アプリケーションを構築しましょう。

メモリ安全な言語、構造的なリエントランシー防止、および統合された形式検証の組み合わせにより、Aptos と Sui はリスクの高い DeFi アプリケーションにとって強力なプラットフォームとなっています。Move は安全なスマートコントラクトを書きやすくするだけでなく、特定の種類の壊滅的な失敗を数学的に不可能にします。


参照元: