I can't add liquidity from the contract for testing with hardhat

Hello everyone,

I want to test some swap functions (swap my token for ETH). In order to do this, I want to test it using Hardhat. For swapping, it needs to have some liquidity so I have to provide liquidity and there is my problem.

I was able to transfer WETH to the owner of MyTokens in order to add liquidity but I am unable to do so.

There is the function addLiquidity :

function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external payable returns (uint, uint, uint) {
        IERC20(tokenA).transferFrom(msg.sender, address(this), amountADesired);
        IERC20(tokenB).transferFrom(msg.sender, address(this), amountBDesired);
        IERC20(tokenA).approve(UNISWAP_V2_ROUTER, amountADesired);
        IERC20(tokenB).approve(UNISWAP_V2_ROUTER, amountBDesired);

        (uint amountToken, uint amountETH, uint liquidity) = IUniswapV2Router02(UNISWAP_V2_ROUTER).addLiquidity(
                tokenA,
                tokenB,
                amountADesired,
                amountBDesired,
                amountAMin,
                amountBMin,
                to,
                deadline
            );
        return (amountToken, amountETH, liquidity);
    }

This is the test file :

//...
TestRewardERC20 = await ethers.getContractFactory("TestRewardERC20", owner);
mt = await TestRewardERC20.deploy();

const amountADesired = 50000;
const amountAMin = 5000;
const amountBDesired = 100;
const amountBMin = 1;

await mt.approve(mt.address, amountADesired);
await WETHContract.approve(mt.address, amountBDesired);
const latestBlock = await ethers.provider.getBlockNumber();
const timestamp = (await ethers.provider.getBlock(latestBlock)).timestamp;

await mt.addLiquidity(
      mt.address,
      WETHAddress,
      amountADesired,
      amountBDesired,
      amountAMin,
      amountBMin,
      owner.address,
      timestamp2 + 1000
    );

This is the hardhat .config file :

//...
defaultNetwork: "hardhat",
  networks: {
    hardhat: {
      forking: {
        url: `https://eth-mainnet.alchemyapi.io/v2/CwCV16rJMJOAXnbqJxj2esvQIYLTCKph`,
        blockNumber: 14638929,
      },
    },

When I run "npx hardhat test" I have either "TRANSFER_FROM_FAILED" either "Error: Transaction reverted without a reason string." depending on what I change.

Thank you very much for any help, have a great day :slight_smile:

I would note that this looks really wrong.
It's not really clear what mt is, since you did not post your TestRewardERC20 contract in full, but I'd expect the Token contract (where all balances are stored) and the Pool contract (which supports liquidity management) to be two separate entities.

FYI, there is no reason to approve an account (mt in your case) to transfer from itself.
So there's technically no need for that line in your script.

However, my main point is not about the redundancy of this line, but about this line implying of something fundamentally wrong in your design (of the contract pointed by mt).

Hello, thank you for your answer,

I didn't share the TestRewardERC20 contract because it is just a very simple ERC20 token, I only want to provide liquidity (MyToken / WETH) in order to do some test in the future but I can't do it.

( mt = await TestRewardERC20.deploy() )

I changed few things :

In my test file, I send token and WETH to "owner" and I want to add liquidity so I use mt.addLiquidity(...) but no matter what changes I make I always get the TRANSFER_FROM_FAILED error when I run "npx hardhat test", I'm a bit lost...

You haven't responded to my main point:

await mt.approve(mt.address, amountADesired)

Why are you approving mt to transfer tokens from itself?

Most likely, there is someone else that you should approve (the error-message implies that, BTW).