Puppet V2

Description

The developers of the previous pool seem to have learned the lesson. And released a new version!

Now they’re using a Uniswap v2 exchange as a price oracle, along with the recommended utility libraries. That should be enough.

You start with 20 ETH and 10000 DVT tokens in balance. The pool has a million DVT tokens in balance. You know what to do.

TL;DR

Similar to the previous chall but with some minor modifications.

Code Audit

The price calculation looks "formal" this time:

    function _getOracleQuote(uint256 amount) private view returns (uint256) {
        (uint256 reservesWETH, uint256 reservesToken) =
            UniswapV2Library.getReserves(_uniswapFactory, address(_weth), address(_token));
        return UniswapV2Library.quote(amount * (10 ** 18), reservesToken, reservesWETH);
    }

But looking into the implementation of UniswapV2Library.quote(), we see this computation is not different from the one in previous chall:

    function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) internal pure returns (uint256 amountB) {
        require(amountA > 0, "UniswapV2Library: INSUFFICIENT_AMOUNT");
        require(reserveA > 0 && reserveB > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY");
        amountB = (amountA * reserveB) / reserveA;
    }

Note that again we have a lot of dvt tokens and ETH compared to the uniswap v2 pool, therefore it is easy to manipulate the price by swapping all dvt for ETH, just like what we did in the previous chall.

One gotcha here, ETH liquidity was added during the setup instead of WETH:

Therefore if we use swapExactTokensForTokens() to swap dvt for WETH, we won't get much WETH back because of low liquidty. Here we should use swapExactTokensForETH() to swap dvt for ETH first and then deposit ETH for WETH.

Building PoC

This PoC is just a modified version of the previous chall.

Last updated