banner
zach

zach

github
twitter
medium

ダム・ヴァルナラブル・ディファイ | 止められない

#チャレンジ#1 - 止まらない

止まらない

コントラクト#

  • ReceiverUnstoppable:IERC3156FlashBorrower コントラクトを継承し、フラッシュローンを発行し、フラッシュローン後のコールバックを実行するためのものです。
  • UnstoppableVault:フラッシュレンダー、ERC4626 を継承した金庫コントラクトで、フラッシュローンをサポートしています。

スクリプト#

  • DamnValuableToken、UnstoppableVault コントラクトを順番にデプロイします。
  • TOKENS_IN_VAULT の数のトークンを金庫に入れ、INITIAL_PLAYER_TOKEN_BALANCE の数のトークンをプレイヤーユーザーに転送します。
  • ReceiverUnstoppable コントラクトをデプロイします。
  • 攻撃スクリプトを実行します。
  • ReceiverUnstoppable がフラッシュローンのトランザクションを revert することを期待します。

解決策#

攻撃の目標は、ReceiverUnstoppable コントラクトを介して実行される executeFlashLoan メソッドが revert されることです。まず、executeFlashLoan の呼び出しフローを分析します。

image

重要なのは、UnstoppableVault.flashLoan メソッドで、次の操作が行われます。

  • フラッシュローン前の残高を計算する:totalAssets ()
  • 現在のシェアを計算する:convertToShares (totalSupply) が前の計算で得られた残高と一致するかどうか
  • フラッシュローン手数料を計算する:flashFee
  • amount 個のトークンをレシーバーに転送し、レシーバーの onFlashLoan メソッドを呼び出してコールバックを実行する
  • amount + fee の数のトークンをレシーバーから転送する
  • fee を feeRecipient アカウントに転送して、フラッシュローンを完了する

トランザクションを revert させるためには、convertToShares(totalSupply) != totalAssets()となるようにする必要があります。

これらの関数は、ERC4626 で定義されているものであり、このプロトコルについては以下の記事を参照してください:
WTF-Solidity/51_ERC4626/readme.md at main · WTFAcademy/WTF-Solidity

簡単に言えば、ERC20 の組み合わせであり、アセットトークンとシェアトークンの組み合わせです。アセットを預け入れたり引き出したりすると、対応する数のシェアトークンが鋳造または破棄されます。

  • totalAssets():現在の金庫のアセットトークンの数を計算します。
  • convertToShares(totalSupply):totalSupply は総シェアトークンの数です(預け入れまたは鋳造のみの場合にのみ発生します)。convertToShares は、assets * totalSupply /totalAssets () を計算するものです。

これらの 2 つが一致しないようにするには、UnstoppableVault にトークンを預け入れるための depost または mint メソッドを使用しないだけです。したがって、攻撃スクリプトの内容は次のようになります:

it('Execution', async function () {
        /** CODE YOUR SOLUTION HERE */
        const dvtForPlayer  = token.connect(player);
        await dvtForPlayer.transfer(vault.address,1);
    });
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。