Day12 実行ログ(2026-07-22 更新)
実装
- 脆弱/安全コントラクト:
contracts/VulnBank.sol,SafeBank.sol,Attacker.solを追加。VulnBankはCEI違反(bal更新が送金後)で再入攻撃可能、SafeBankはReentrancyGuard+ CEI 順守。 - 権限管理例:
contracts/AdminBox.sol(Ownable + Pausable)。 - テスト:
test/reentrancy.tsを実装し、VulnBankが攻撃で枯渇する一方、SafeBankは攻撃Txがrevertすることを確認。 - Foundry invariant:
test/Invariant.t.solで、3 actorの内部台帳合計・contract assets・ghost net depositsの一致をstatefulに検査。test-negative/UnsafeAccountingInvariant.t.solの1 wei mutationが同じpropertyを破ることも自動確認。
コマンド
# 依存を復元(OZ v5)
npm run install:reviewed
# 再入テストのみ
npx hardhat test test/reentrancy.ts
# 全体テスト
npm test
# Foundry v1.7.1: executable invariant + expected-failure mutation
npm run test:foundry
結果:test/reentrancy.ts は 2 passing。Hardhat全体は既存Mocha 16件とSolidity invariant 1件の計17件が成功した。Foundryの通常invariantは128 runs / 4,096 calls / revert 0で成功し、negative mutationは期待どおり非0終了して検出された。
観測
VulnBankへ10 ETH預けた状態でAttacker.attack()を実行すると、bal[msg.sender]が未更新の間に再入され、残高が9 ETH未満まで減少。SafeBankはnonReentrant+ 先に残高更新を行うため、攻撃Txは revert し drain 不発。AdminBox(Ownable+Pausable)は Day04/Day11 のサンプルに適用できる汎用テンプレートとして用意。
静的解析/ファジング
- Foundry v1.7.1でhandler、target contract、bounded input、ghost accountingを使う実行可能invariantを確認済み。
- Slither / Echidna は外部ツール導入と追加設定が必要なため実行していません。手順メモ:
pipx install slither-analyzerslither . --filter-paths node_modules- Echidnaを追加する場合は、Foundryと別ツールであることを維持し、propertyとtargetを個別に定義する。
まとめ
- Day12 で扱う再入/権限対策をコードベースに具体化し、攻撃成功/失敗を自動テストで確認できる状態にした。
AdminBoxなどのアクセスポリシー雛形を追加したことで、教材の他コントラクトにも Pausable/Ownable を適用しやすくなった。- 通常green invariantだけでなく、意図的なaccounting欠陥を検出するnegative fixtureにより、propertyが反証可能であることを固定した。