0

I try to test my smart contract with hardhat. At first I am forking the polygon mainnet like this:

npx hardhat node --fork https://polygon-mainnet.g.alchemy.com/v2/...

after this I can run the test local with:

npx hardhat test --network local

Now I want to test a swap with uniswapV2Router. So I want to fund my contract with a few tokens. Because of hardhat creating a few wallets with a lot of eth in it, I try to send eth (Should be matic in my case right?) from a wallet to my contract, but the balance in my contract is still 0. So at first, how is my smart contract looking like:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "hardhat/console.sol";
import "./interfaces/IUniswapV2Router02.sol";

contract MakeSwap is {
    address private owner;
    IUniswapV2Router02 public quickRouter;

    constructor(
        address _quickRouter
    ) {
        owner = msg.sender;
        quickRouter = IUniswapV2Router02(_quickRouter);
    }
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    receive() external payable {}

    function swapExactTokensForTokensQuick(
        uint256 _amountIn,
        uint256 _amountOutMin,
        address _tokenIn,
        address _tokenOut,
        uint256 deadline
    ) external returns (uint256) {
        IERC20(_tokenIn).approve(address(quickRouter), _amountIn);
        address[] memory path;
        path = new address[](2);
        path[0] = _tokenIn;
        path[1] = _tokenOut;
        uint256[] memory amounts = quickRouter.swapExactTokensForTokens(
            _amountIn,
            _amountOutMin,
            path,
            address(this),
            deadline
        );
        console.log(amounts[1]);
        return amounts[1];
    }
}

And I am testing the swap like this:

const { SignerWithAddress } = require("@nomiclabs/hardhat-ethers/signers");
const { expect } = require("chai");
const { ethers } = require("hardhat");
const {
  IERC20,
} = require("../artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.json");
const token_Address_usdc = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const token_Address_weth = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";
const token_Address_wmatic = "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270";
const router_quick = "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff";
const erc20_abi = require("../abis/erc20abi.json");
const weth_abi = require("../abis/wethabi.json");

describe("test", () => {
  let Contract, owner, addr1, addr2;

  beforeEach(async () => {
    [owner, addr1, addr2, _] = await ethers.getSigners();
    factory = await ethers.getContractFactory("MakeSwap");
    Contract = await factory.deploy(router_quick);
    await Contract.deployed();

    const weth = new ethers.Contract(token_Address_weth, erc20_abi, ethers.provider);
    const usdc = new ethers.Contract(token_Address_usdc, erc20_abi, ethers.provider);
    const wmatic = new ethers.Contract(token_Address_wmatic, erc20_abi, ethers.provider);

    var contractBalance_weth = await weth.balanceOf(Contract.address);
    var contractBalance_usdc = await usdc.balanceOf(Contract.address);
    var contractBalance_wmatic = await wmatic.balanceOf(Contract.address);
    console.log("WETH Balance: ", contractBalance_weth.toString());
    console.log("USDC Balance: ", contractBalance_usdc.toString());
    console.log("WMATIC Balance: ", contractBalance_wmatic.toString());

    //Wallet #17 -> Should have 10000 ETH -> Created from hardhat
    const priv_key_17 =
      "0x...";
    const addr_17 = "0x...";

    const signer = await ethers.provider.getSigner(addr_17);
    await signer.sendTransaction({
      to: Contract.address,
      value: ethers.utils.parseUnits("1", 18),
    });

    var contractBalance_weth = await weth.balanceOf(Contract.address);
    var contractBalance_usdc = await usdc.balanceOf(Contract.address);
    var contractBalance_wmatic = await wmatic.balanceOf(Contract.address);
    console.log("WETH Balance: ", contractBalance_weth.toString());
    console.log("USDC Balance: ", contractBalance_usdc.toString());
    console.log("WMATIC Balance: ", contractBalance_wmatic.toString());
  });

  describe("trade", async () => {
    it("Should create a trade", async () => {
      const weth = new ethers.Contract(token_Address_weth, erc20_abi, ethers.provider);
      const usdc = new ethers.Contract(token_Address_usdc, erc20_abi, ethers.provider);
      const wmatic = new ethers.Contract(token_Address_wmatic, erc20_abi, ethers.provider);

      const timestamp = (await ethers.provider.getBlock("latest")).timestamp;
      const deadline = timestamp + 3000;

      amountOutMin = ethers.utils.parseUnits("2000", 6);
      amountIn = ethers.utils.parseUnits("1", 18);
      var contractBalance_weth = await weth.balanceOf(Contract.address);
      var contractBalance_usdc = await usdc.balanceOf(Contract.address);
      var contractBalance_wmatic = await wmatic.balanceOf(Contract.address);
      console.log("WETH Balance: ", contractBalance_weth.toString());
      console.log("USDC Balance: ", contractBalance_usdc.toString());
      console.log("WMATIC Balance: ", contractBalance_wmatic.toString());
      await Contract.provider.send("hardhat_setBalance", [
        Flashloan.address,
        ethers.utils.parseUnits("5", 18).toHexString(),
      ]);
      var contractBalance_weth = await weth.balanceOf(Contract.address);
      var contractBalance_usdc = await usdc.balanceOf(Contract.address);
      var contractBalance_wmatic = await wmatic.balanceOf(Contract.address);
      console.log("WETH Balance: ", contractBalance_weth.toString());
      console.log("USDC Balance: ", contractBalance_usdc.toString());
      console.log("WMATIC Balance: ", contractBalance_wmatic.toString());
      await expect(
        Contract.swapExactTokensForTokensSushi(
          amountIn,
          amountOutMin,
          token_Address_weth,
          token_Address_usdc,
          deadline
        )
      ); //.to.not.reverted;
      var contractBalance_weth = await weth.balanceOf(Contract.address);
      var contractBalance_usdc = await usdc.balanceOf(Contract.address);
      var contractBalance_wmatic = await wmatic.balanceOf(Contract.address);
      console.log("WETH Balance: ", contractBalance_weth.toString());
      console.log("USDC Balance: ", contractBalance_usdc.toString());
      console.log("WMATIC Balance: ", contractBalance_wmatic.toString());
    });
  });
});

And here I can start the test, and it is running without any error which leads to stop the test. But in the log it says: eth_sendTransaction in red with additional information: Error: VM Exception while processing transaction: reverted with reason string 'TransferHelper: TRANSFER_FROM_FAILED' and for all the test process my console.log(...) statements say balance is 0:

WETH Balance:  0
USDC Balance:  0
WMATIC Balance:  0
WETH Balance:  0
USDC Balance:  0
WMATIC Balance:  0
WETH Balance:  0
USDC Balance:  0
WMATIC Balance:  0
WETH Balance:  0
USDC Balance:  0
WMATIC Balance:  0
WETH Balance:  0
USDC Balance:  0
WMATIC Balance:  0

Can someone help me to fund my contract and make a swap? If there is information missing, please tell me and I will add it.

Thank you!

3
  • Are you strictly tied to polygon mainnet? I have experience with hardhat and was able to test my contracts with default hardhat chain. Their official docs are quite good hardhat.org/hardhat-runner/docs/guides/test-contracts.
    – Gleichmut
    Oct 26, 2022 at 6:28
  • what u mean with default hardhat chain?
    – Dani S
    Oct 27, 2022 at 12:40
  • Based on my understanding hardhat supply within its packages locally deployed chain or software which emulates chain's behaviour. By simply run default configuration you are able to test your contracts over this chain. Off topic: at this moment personally I found the most convenient to work with own locally deployed private chain for prototyping my product.
    – Gleichmut
    Jan 5, 2023 at 9:32

2 Answers 2

0

Another way would be to deploy the contract on the mumbai testnet, get some matic from a faucet and then sending it to your contract. This is how I usually do my testing and it works. If you are having a problem with the specific function from the uniswap's router, as long as its v2, write again, i will try to help you out.

3
  • If this is working on mumbai testnet, it should also work on forekd mainnet doesn't it? Do you have a explanation how this works? Because I think you add matic to your wallet with the faucet and then transfer it to your contract. And I do have some wallets with matic but cannot send it to the contract -> Now, this looks for me as the process of sending matic to the contract should work the same. Can you show me how you do it? Thank you!
    – Dani S
    Oct 27, 2022 at 8:10
  • 1 Option is to deploy it with a hardhat task and script. It is easy but requires manual configuration of the hardhat-config file. There are many youtube videos on how to do that. 2. The approach that I will tell you know is very amateur, but does the job well and has the same end result. it is also very beginner friendly: 1. get some test matic over at mumbaifaucet.com 2. go to remix.ethereum.org 3. Create a new contract file 4. Paste the code in it. 5. In the Solidity compiler tab, make sure that the selected compiler is at least 0.8.4 or later Oct 27, 2022 at 8:20
  • 6. Go to the deploy and run tab. 7. connect your Metamask to the Mumbai Testnet of Polygon. 8. In the environment dropdown menu , select " Injected Provider - Metamask " 9. Hit deploy to deploy the contract. 10. Send the test Matic that you got from the faucet to the address of the already deployed contract ( leave some matic in the wallet in order to do some test transactions if you need ) Hope that helps! Oct 27, 2022 at 8:24
0

So I found a way to transfer wmatic (Or eth on ethereum network) to my contract:

describe("receive", async () => {
    it("Should send tokens", async () => {
      const provider = ethers.provider;

      expect(await provider.getBalance(Contract.address)).to.equal(0);

      await addr1.sendTransaction({
        to: Contract.address,
        value: 100,
      });
      console.log(await provider.getBalance(Contract.address));
      expect(await provider.getBalance(Contract.address)).to.equal(100);
    });
  });

Is it possible to send other tokens as well? Or do I have to add funtions in my smart contract for that?

1
  • Please, create a new question for the token transfers.
    – Ismael
    Oct 29, 2022 at 20:47

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.