1

I have a very simple smart contract for a MOCK coin where I need a mint function to be able to be run by any address as it is just for testing. I took the code from OpenZepplin and removed OnlyOwner.

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "hardhat/console.sol";

contract MockUSDC is ERC20 {
    constructor() ERC20("USDC", "USC") {}

    function mint(address to, uint256 amount) public {
        console.log("Minting %s tokens to the address %s", amount, to);
        _mint(to, amount);
        console.log("Post Mint");
    }
}

I have a test which code is like this

            it("Should succesfully Swap Token for a Token", async function () {
                const [deployer, swapper] = await ethers.getSigners()

                const {wethToken, usdcToken, someToken} = await loadFixture(deployMockCoinsFixture)
                const {mockUniRouter} = await loadFixture(deployMockUniswapV2Router)

                const swapAmount = ethers.utils.parseEther("1000")
                console.log(swapAmount)
                console.log(swapper.address)

                //Send some token to the swapper adress
                try {
                    console.log('Minting...')
                    await usdcToken.connect(swapper).mint(swapper.address,swapAmount )
                    console.log('Minted USDC')
                } catch (error) {
                    console.error('Error minting USDC', error)
                }
                
                //Assert the mint
                expect(await usdcToken.balanceOf(swapper.address)).to.equal(swapAmount)
})

When I run a local node with hardhat node and do test, all my deployments pass test by when it gets to the mint function it gets stuck on the line console.log('Minting...') The console.log statements from inside the contract are not run.

I tried: Using BigInt, using an int, parseEther, tx.wait() usdcToken.connect(swapper), usdcToken.connect(swapper.address) cleaning, recompiling, contract and filename is the same OpenZeppelin is installed, hardhat.config.js is correct

I looked up google, even spoken with chat GPT 4. The test connects to the node as I see the logs and I see contracts being deployed.

I am new to unit testing, hardhat, mocha, chai, truffle and Node JS (I was a .Net,Python guy), and documentation of hardhat is mostly tutorials. Maybe I missed something in the documentation.

I am not asking for a specific answer, if it is a lot of work on your side. If you can link me the object-specific documentation where all functions,errors and libraries of hardhat are documented, like msdn. I can't seem to find it Thank you for taking your time.

2
  • Can you edit your answer and also add the deployMockCoinsFixture and deployMockUniswapV2Router fixtures? May 13, 2023 at 13:34
  • I have added the minum code so there is no uneeded analysis. These fixtures are run in seperate tests and work correctly. (Are being deployed). May 15, 2023 at 10:21

3 Answers 3

0

It looks like the issue is with the way you are calling the mint function. Instead of usdcToken.connect(swapper.address).mint(swapper.address,swapAmount ), try using usdcToken.connect(swapper).mint(swapper.address,swapAmount ). The connect function takes the Signer instance as an argument, not the address.

So your updated test code should look like this:

//Send some token to the swapper adress
try {
    console.log('Minting...')
    await usdcToken.connect(swapper).mint(swapper.address, swapAmount)
    console.log('Minted USDC')
} catch (error) {
    console.error('Error minting USDC', error)
}

This should resolve the issue and allow the mint function to be called successfully.

1
  • Thank you for taking your time, but I have tried this, It gets stuck on Minting... and i get the Mocha timeout error. May 12, 2023 at 14:26
0

I managed to find a solution to the problem you were facing. The issue was related to the way you were interacting with the mint function in the contract using Hardhat.

The problem was that you were trying to call the mint function using the swapper address as the signer. However, the swapper address did not have the necessary permissions to perform the mint operation. In the context of the ERC20 standard, typically the contract deployer or a specific role (like an minter role) has the permission to mint new tokens. In this updated version of the test, I'm connecting to the usdcToken contract with the deployer account to call the mint function. This allows the mint function to execute successfully.

Here's the corrected code:

const { ethers } = require('hardhat');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { expect } = require('chai');

async function deployMockUSDCFixture() {
    const [deployer] = await ethers.getSigners();

    const MockUSDCFactory = await ethers.getContractFactory('MockUSDC');
    const usdcToken = await MockUSDCFactory.connect(deployer).deploy();

    return { usdcToken };
}

describe('MockUSDC', function () {
    it('Should successfully mint tokens', async function () {
        const [deployer, swapper] = await ethers.getSigners();

        const { usdcToken } = await loadFixture(deployMockUSDCFixture);

        const mintAmount = ethers.utils.parseEther('1000');
        console.log(mintAmount);
        console.log(swapper.address);

        // Mint some tokens to the swapper address
        try {
            console.log('Minting...');
            await usdcToken.connect(deployer).mint(swapper.address, mintAmount);
            console.log('Minted USDC');
        } catch (error) {
            console.error('Error minting USDC', error);
        }

        // Assert the mint
        expect(await usdcToken.balanceOf(swapper.address)).to.equal(mintAmount);
    });
});
3
  • Please read the code of the contract I posted above. I removed the OnlyOwner mechanic as it is not needed for the test. When the above contract is pasted and deployed in Remix IDE on Remix VM netoworks it works perfectly and any address can mint the coins. May 16, 2023 at 21:31
  • Yes, you can replace deployer with swapper or any other account. The mint function in your MockUSDC contract doesn't have any access controls and can be called by any address. Here's how you can do it: await usdcToken.connect(swapper).mint(swapper.address, mintAmount); May 17, 2023 at 11:37
  • I have tried that, still stuck. May 17, 2023 at 12:09
0

The issue was actually very simple. In the code in this place:

const {wethToken, usdcToken, someToken} = await loadFixture(deployMockCoinsFixture)
const {mockUniRouter} = await loadFixture(deployMockUniswapV2Router)

I am using 2 fixtures which is the problem. A fixture creates a snapshot of the local blockchain, which there can exist only one at a time so basically the deployMockUniswapv2Router will overwrite the previous fixture and coins will be deleted hence the usdcToken variable will point to non existatnt contract while not being undefined (as it was initialized when the first fixture run).

I basically changed both fixtures into a single fixture.

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.