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);

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;

3 Answers 3


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.


This also happens if the Uniswap token related to the pool has not been approved for the wallet sending the transaction.

Solution: Call the approve method of the new Pair contract with spender as 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D

  • Perfect Thanks!
    – Richard
    Aug 20, 2021 at 8:31

"UniswapV2 addLiquidity revert ds-math-sub-underflow" error happened because "msg.value" parameter has not been provided for calling "addLiquidity" method.

Now call the addLiquidity method as:

await uniswapV2Router02.addLiquidity(token0.address, token1.address, 500, 250, 250 , 125, accounts[0], 1618158769, {value : "125"});

The same "value" parameter should also be passed for calling swap methods like "swapExactETHForTokens".

This is the exact reason for this error.

Note: Don't forget to change the deadline parameter in the function:

addLiquidity(address tokenA,address tokenB,uint amountADesired, uint amountBDesired,uint amountAMin,uint amountBMin,address to,uint deadline)

  • Thanks! the addition of {value:125} to addLiquidityEth got around my issue of TransferHelper: TRANSFER_FROM_FAILED.
    – rsmets
    Mar 2 at 17:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.