Damn Vulnerable DeFiは、DeFi スマートコントラクト攻撃のチャレンジシリーズです。内容には、フラッシュローン攻撃、レンディングプール、オンチェーンオラクルなどが含まれています。始める前に、Solidity および JavaScript に関連するスキルが必要です。各問題に対して、単体テストがパスすることを確認する必要があります。
問題リンク:https://www.damnvulnerabledefi.xyz/challenges/3.html
問題の説明:
レンディングプールコントラクトがあり、DVT トークンのフラッシュローン機能を提供しています。このプールには 100 万個のトークンがありますが、あなたは一つも持っていません。あなたがする必要があるのは、一つのトランザクションでこのレンディングプールのトークンをすべて取り出すことです。
まず、レンディングプールコントラクトのソースコードを見てみましょう。
TrusterLenderPool.sol
このスマートコントラクトからわかるように、flashLoan メソッドを使用してすべてのトークンを取り出すことはできません。なぜなら、最後に残高のチェックが行われ、条件を満たさない場合はトランザクションがロールバックされるからです。
別のアプローチを考えてみましょう。もし、token コントラクトの transferFrom メソッドを呼び出すことができれば、次のようになります。
これにより、レンディングプールコントラクトのトークンが attacker アドレスに移動するため、目的を達成できます。
しかし、transForm を成功させるためには、token コントラクトの承認が必要です。ERC20 標準では、spender が呼び出し元のアカウントから amount のトークンを使用することに同意するための approve メソッドがあります。
この問題では、次のように借り手プールコントラクトで次のようなメソッドを呼び出すことができます:
つまり、呼び出し元(借り手プールコントラクト)が attacker アドレスに amount のトークンを使用することに同意します。
しかし、借り手プールコントラクトには呼び出す場所がありませんが、flashLoanメソッドの内部でtarget.functionCall(data)というコードがあることに気付きます。これは、内部でtarget.call(data)を実行しています。
スマートコントラクト間の相互作用はすべて calldata を介して行われます。例えば:
0x6057361d000000000000000000000000000000000000000000000000000000000000000a
最初の 4 バイト(6057361d)は関数のセレクタ(関数の識別子)であり、残りの部分は関数に渡される入力パラメータです。
コントラクト内で calldata を構築するために、abi.encodeWithSignature ("関数名 (... パラメータの型)", ...params) を使用できます。
したがって、この問題では、target は token コントラクトのアドレスであり、data は approve メソッドです。以下のように JavaScript で data を構築できます。
その後、flashLoan メソッドを呼び出し、対応するパラメータを渡すことができます。成功した場合、レンディングプールコントラクトの残高は attacker が操作できるようになります。以下はコードの例です。
yarn trusterを実行してテストを実行します。テストがパスすることを確認します。
しかし、問題では一つのトランザクションを実行する必要がありますが、私たちのコードは要件を満たしていません。そのため、スマートコントラクトを使用してトランザクションを実行できます。
TrusterAttack.sol
その後、テストケースでコントラクトをデプロイし、attack メソッドを実行します。
最後に、yarn trusterを実行してテストを実行します。テストがパスすることを確認します。