---
title: Deploy Your First ERC‑20 Token on Polygon with Hardhat: A Complete Developer Guide
siteUrl: https://logzly.com/chaincraft
author: chaincraft (ChainCraft)
date: 2026-06-22T10:05:45.486454
tags: [saas, blockchain, web3]
url: https://logzly.com/chaincraft/deploy-your-first-erc20-token-on-polygon-with-hardhat-a-complete-developer-guide
---


You’ve probably heard “ERC‑20” tossed around in every dev chat, but until you actually push one to a live network it feels like a myth. Polygon’s low fees and fast finality make it the perfect sandbox for a first token, and Hardhat gives you the tooling to do it without pulling your hair out. In this post I’ll walk you through every step, from setting up the project to seeing your token on a block explorer. Grab a coffee, fire up your terminal, and let’s get our hands dirty.

## Why Polygon and Hardhat?

Polygon (formerly Matic) is essentially Ethereum’s cheaper cousin. It runs the same EVM bytecode, so any Solidity contract you write for Ethereum works there unchanged. The big win is that a transaction that costs $5 on mainnet is often under $0.01 on Polygon. For a beginner token, that means you can experiment without watching your wallet melt.

Hardhat is a development environment that feels like a Swiss‑army knife. It compiles, runs tests, spins up a local node, and even lets you fork live networks. The community plugins for ethers, waffle, and upgrades make it a one‑stop shop for most Web3 projects. If you’ve used Truffle or Remix before, Hardhat’s workflow will feel familiar but far more flexible.

## Prerequisites

Before we dive in, make sure you have:

- Node.js (v16 or later) and npm installed.
- A code editor – VS Code works great.
- A MetaMask wallet with some MATIC on the Polygon Mumbai testnet (you can get free test MATIC from the faucet).
- Basic familiarity with Solidity and the ERC‑20 standard.

If any of these are missing, pause and get them sorted. Trust me, half the frustration comes from missing a tiny setup step.

## Step 1: Bootstrap the Hardhat Project

Open a terminal and run:

```
mkdir my-polygon-token
cd my-polygon-token
npm init -y
npm install --save-dev hardhat
npx hardhat
```

When the Hardhat wizard asks what you want to create, choose “Create a basic sample project”. This scaffolds a `contracts/`, `test/`, and `scripts/` folder plus a `hardhat.config.js` file.

### Install Additional Packages

We’ll need ethers for interacting with the blockchain and dotenv for keeping our private key safe:

```
npm install --save-dev @nomiclabs/hardhat-ethers ethers dotenv
```

Add the plugin to `hardhat.config.js`:

```js
require("@nomiclabs/hardhat-ethers");
require("dotenv").config();
```

## Step 2: Write the ERC‑20 Contract

Inside `contracts/` create a file called `MyToken.sol`. Keep it simple – we’ll inherit from OpenZeppelin’s battle‑tested implementation.

First, install OpenZeppelin contracts:

```
npm install @openzeppelin/contracts
```

Now the contract:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

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

contract MyToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply);
    }
}
```

A quick rundown:

- `ERC20` is the standard interface that defines `balanceOf`, `transfer`, etc.
- The constructor sets the token name and symbol, then mints the initial supply to the deployer’s address.
- `initialSupply` is expressed in wei‑like units, so if you want 1,000 tokens with 18 decimals you pass `1000 * 10**18`.

## Step 3: Configure Hardhat for Polygon Mumbai

Open `hardhat.config.js` and add a network entry:

```js
module.exports = {
  solidity: "0.8.20",
  networks: {
    mumbai: {
      url: "https://rpc-mumbai.maticvigil.com",
      accounts: [process.env.PRIVATE_KEY]
    }
  }
};
```

Create a `.env` file in the project root and paste your MetaMask private key (never commit this file!). Also add your Alchemy or Infura endpoint if you prefer a different RPC provider.

```
PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
```

## Step 4: Write a Deployment Script

In `scripts/` create `deploy.js`:

```js
async function main() {
  const [deployer] = await ethers.getSigners();
  console.log("Deploying from:", deployer.address);

  const MyToken = await ethers.getContractFactory("MyToken");
  const initialSupply = ethers.utils.parseUnits("1000000", 18); // 1 million tokens
  const token = await MyToken.deploy(initialSupply);

  await token.deployed();
  console.log("MyToken address:", token.address);
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });
```

A couple of notes:

- `ethers.getSigners()` returns the accounts Hardhat knows about; the first one is the one tied to our private key.
- `parseUnits` converts a human‑readable number into the 18‑decimal format ERC‑20 expects.
- The script logs the contract address so you can verify it later.

## Step 5: Deploy to Mumbai

Run the script:

```
npx hardhat run scripts/deploy.js --network mumbai
```

If everything is wired correctly you’ll see something like:

```
Deploying from: 0xAbc...123
MyToken address: 0xDef...456
```

Copy that address. Open https://polygonscan.com/ and paste it into the search bar. You should see the contract verified (if you haven’t verified yet, you can use the Hardhat verify plugin later). The “Contract” tab will show the name, symbol, and total supply.

## Step 6: Interact with Your Token

Let’s do a quick sanity check using a small Node script. Create `scripts/checkBalance.js`:

```js
async function main() {
  const tokenAddress = "0xDef...456"; // replace with your address
  const MyToken = await ethers.getContractAt("ERC20", tokenAddress);
  const [owner] = await ethers.getSigners();

  const balance = await MyToken.balanceOf(owner.address);
  console.log("Balance of", owner.address, "is", ethers.utils.formatUnits(balance, 18), "MTK");
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });
```

Run it with the same `--network mumbai` flag. You should see the 1 000 000 MTK you minted in the constructor.

## Optional: Verify on Polygonscan

Verification makes your source code public and lets users read the contract directly on the explorer. Install the plugin:

```
npm install --save-dev @nomiclabs/hardhat-etherscan
```

Add to `hardhat.config.js`:

```js
require("@nomiclabs/hardhat-etherscan");
module.exports = {
  // ... existing config
  etherscan: {
    apiKey: process.env.POLYGONSCAN_API_KEY
  }
};
```

Create a Polygonscan API key, drop it in `.env`, then run:

```
npx hardhat verify --network mumbai DEPLOYED_CONTRACT_ADDRESS "1000000000000000000000000"
```

The long number is the initial supply in wei. After a few seconds Polygonscan will show your verified source.

## Common Pitfalls and How to Avoid Them

| Issue | Why it Happens | Fix |
|-------|----------------|-----|
| “invalid opcode” or “out of gas” | Deploying with too low a gas limit or using an outdated Solidity version | Hardhat automatically estimates gas; just let it. Ensure `solidity` version matches the pragma in your contract. |
| “invalid private key” | `.env` not loaded or key missing the `0x` prefix | Double‑check the `.env` file and restart the terminal if needed. |
| Contract not verified | API key missing or wrong format | Verify the key on Polygonscan, then re‑run the verify command. |

## Next Steps

Now that you have a working ERC‑20 on Polygon, you can:

- Add a `mint` function with an `onlyOwner` guard to allow future token issuance.
- Build a simple front‑end with ethers.js to let users transfer tokens.
- Explore Layer‑2 bridges to move your token between Polygon and Ethereum.

Deploying a token is just the first line of code in a longer story. The real fun begins when you start integrating it into a dApp, a game, or a DAO. Keep experimenting, and remember that every bug you squash is a step toward mastery.

Happy coding!