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(
        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(
      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

1 Answer 1


your problem lies in these two lines.

IERC20(tokenA).approve(UNISWAP_V2_ROUTER, amountADesired); IERC20(tokenB).approve(UNISWAP_V2_ROUTER, amountBDesired);

you want to approve the tokens from account to UNISWAP_V2_ROUTER, but when you call a approve function of ERC20 contract from other contract the msg.sender in the ERC20 contract will be the contract not the actual caller(account) who initiates the call, so your tokens get never approved from intended account. And when you try to transfer from that account using transferFrom function, it will fail because it doesn't have approval. What you can do to solve this problem is to call the approve function of ERC20 offchain from the intended account and then go for calling addLiquidity function

  • I am sorry I do not understand very well your answer. What I tried to do is on the test file I sent some tokens and some WETH to "Bob". And I deleted the two lines with "transferFrom" inside the addLiquidity function. My goal is that Bob can call the addLiquidity from the "TestRewardERC20" contract. I did some test and Bob is the actual msg.sender of the function so I don't understand why there is a TRANSFER_FROM_FAILED... Moreover, I am not sure about how to do "call the approve function of ERC20 offchain" Thank you for your time.
    – 0xMente
    Apr 19, 2023 at 13:34
  • Can you define your addLiquidity function what do you want achieve in it. What I see, you are transferring the A and B tokens from bob, and after that your approving the A and B tokens, so from whom you're taking approval, what your function logic suggests that you want approval from Bob so he can add liquidity, but in the testRewardErc20 contract when you implement IERC20.approve, it'll be the testRewardErc20 who approves token not th bob. For calling the approve offchain you need to create a instance of erc20 like you have done for testerc amd call the function as you have called addLiquidi
    – Naveed Ali
    Apr 19, 2023 at 18:09
  • My goal with the addLiquidity function is that the account that calls it (with 2 tokens as input) can add liquidity to this pair. In this case, there is no liquidity, so I would like Bob (who has tokenA from TestRewardERC20 contract and WETH) to add liquidity so that I can test functions where someone exchanges tokenA for WETH. Thank you for your answers !
    – 0xMente
    Apr 20, 2023 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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