UniswapV2 – AddLiquidity Revert DS-Math-Sub-Underflow

ganachesoliditytruffleuniswap

I'm trying to use Uniswapv2Router with Truffle and Ganache, but haven't been able to identify what I'm doing wrong. I'm using addLiquidty method as follows:
await uniswapV2Router02.addLiquidity(token0.address, token1.address, 500, 250, 250 , 125, accounts[0], 1618158769);Which throws error Error: Returned error: VM Exception while processing transaction: revert ds-math-sub-underflow -- Reason given: ds-math-sub-underflow.

But If I comment out .minto(to) The code executes properly until there.

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
        (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
        address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
        TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
        TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
        IUniswapV2Pair(pair);//.mint(to);
    }

This happens even if I have a simple mint implementation just for testing what is going on.

  function mint(address to) external lock returns (uint liquidity) {
        liquidity = 3;
    }

Best Answer

The problem was because when using UniswapV2Factory, only the precompiled UniswapV2Factory contract in the build directories from @uniswap should be deployed as stated in docs https://uniswap.org/docs/v2/smart-contract-integration/quick-start/. So, even if I commented out something on my UniswapV2Pair contract, it had no effect, because UniswapV2Factory uses a precompiled UniswapV2Pair contract as well. On the other hand, the ds-math-sub-underflow error was because on the UniswapV2Pair contract, the function mint(address to) retrieves its balance of each token, and because it hadn't enough, liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); caused an underflow.