教育目的のみであり、投資助言ではありません。リエントランシーの欠陥はコントラクト資産の急速かつ不可逆な損失を招く可能性があり、単一の防御策や監査だけで安全性を証明することはできません。
要点
コントラクトが外部呼び出しを行い、元の実行が完了して不変条件が復元される前に呼び出し先がコールバックすると、リエントランシー攻撃が起こり得ます。古い残高、シェア、権限、価格が見えていれば、コールバックは不整合な状態を使って処理を繰り返したり、別の処理に影響したりできます。
コールバックは同じ関数に入る必要も、ネイティブ通貨を送る必要もありません。トークンフック、NFT受信コールバック、Vaultや戦略の呼び出し、フラッシュローンのコールバックは、信頼できないコードへ制御を渡します。再進入は関数、コントラクト、モジュールをまたぐことがあり、読み取り専用の再進入で別プロトコルが一時的な値を使う場合もあります。
仕組み
典型的な悪用手順は次のとおりです。
- 攻撃者が状態変更関数に入り、最初のチェックを通過します。
- 脆弱なコントラクトが記帳を終える前に、アドレス、トークン、プロトコルを呼び出します。
- 攻撃者のコードが古い状態を参照できる間に、元のコントラクトまたは接続先へ入ります。
- ネストした呼び出しが効果を繰り返すか共有状態を変更し、不変条件が壊れたまま実行が戻ります。
外部への制御移譲は低レベル呼び出しのように明示的な場合も、トークン転送、受信フック、セーフミント、戦略アダプター、任意呼び出しインターフェースに隠れる場合もあります。revert は通常その呼び出しツリーを巻き戻しますが、攻撃者は価値を抜き取るか記帳を壊した後に正常終了するネスト処理を構成できます。
防御は重ねて実装します。
- Checks-Effects-Interactionsに従い、検証、関連する内部状態の確定、外部操作の順に実行します。
- 明白な呼び出しを持つ関数だけでなく、保護対象の不変条件を共有する全入口にガードを適用します。
- 適切な場合は受取側が請求する方式を使い、信頼できないトークン、受信者、フック、プロキシ、統合先への呼び出しを減らします。
- コントラクト間の不変条件を定義し、悪意あるコールバック、関数横断経路、ネストしたマルチコール、読み取り側をテストします。
- 設計が許す場合は、実装レビューと監視、一時停止、インシデント対応を組み合わせます。
例
値を送った後にだけ利用者残高を消去するVaultを考えます。
function withdraw() external {
uint256 amount = balances[msg.sender];
require(amount > 0, "empty balance");
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok, "transfer failed");
balances[msg.sender] = 0;
}受信者は balances[msg.sender] に古い金額が残ったまま制御を得ます。受信関数から withdraw() を再度呼び、同じチェックを通って追加送金を要求できます。呼び出し前に残高を更新すればこの窓は閉じ、ガードはネストした進入を拒否できます。ただし別の入口や接続先が同じ未確定の不変条件を公開し得るため、システム全体の安全性は証明されません。
リスク
- ガードが一つの関数だけを守り、別の関数が同じ状態を公開します。
- 局所的な呼び出し順序は正しくても、コントラクト間の不変条件がコールバック中に不整合です。
- トークン、受信者、フラッシュローンコールバック、戦略アダプターが予期せず外部コードを実行します。
- view関数が一時的な価格や交換率を公開し、別プロトコルが同一トランザクションで利用します。
- アップグレード、モジュール、ストレージ配置の変更が元のロックを迂回または破損します。
- テストが再帰的な出金だけを扱い、関数横断、コントラクト横断、読み取り専用経路を見落とします。
利用者にとって、監査済み表示やガードは対策の証拠であって保証ではありません。アップグレード、統合、特権的な緊急操作は攻撃面を変えます。承認とエクスポージャーを制限し、デプロイ済み実装を確認し、損失を取り消せると想定しないでください。
よくある誤解
- リエントランシーは一つの出金関数を繰り返すだけです。 別の関数やコントラクトへ入ることも、読み手に不整合なデータを見せるだけの場合もあります。
- コールバックはネイティブ通貨の送金だけで起きます。 トークン規格、受信フック、プロトコル統合も外部コードを実行できます。
- ガードやChecks-Effects-Interactionsで安全になります。 適用範囲、共有する全入口、コントラクト間の不変条件は引き続きレビューが必要です。
- 監査に合格すれば再進入はありません。 監査の範囲は限定され、後の変更や未レビューの統合が新経路を作り得ます。
関連トピック
情報源
- セキュリティ上の考慮事項 - Solidity Documentation (参照日: 2026-08-21)
- スマートコントラクトのセキュリティ - ethereum.org (参照日: 2026-08-21)
- ReentrancyGuard - OpenZeppelin Documentation (参照日: 2026-08-21)
- SC08:2026 リエントランシー攻撃 - OWASP Smart Contract Security (参照日: 2026-08-21)