Simple ERC-20 (fixed supply + Permit) using Hardhat + TypeScript.
- Node 22 LTS (recommend nvm-windows)
nvm install 22
nvm use 22
node -v
npm -v- Git and VS Code (recommended)
git clone https://github.com/jspruance/erc20-token-2025.git
cd erc20-tokenIf you’re following the video, this repo contains a
token_complete/folder you’ll copy files from later.
cd token_build
npx hardhat --init- Choose TypeScript template
- Choose Ethers / TypeScript tooling (if asked)
- Yes to install recommended dependencies
npm install @openzeppelin/contracts
npm install dotenvSEPOLIA_RPC_URL=
PRIVATE_KEY=
ETHERSCAN_API_KEY=Notes
- Use a throwaway dev wallet (testnet only).
- Keep the
0xprefix onPRIVATE_KEY. - Never commit
.env(Hardhat template usually git-ignores it—double-check).
Copy these into your Hardhat project:
contracts/MyToken.soltest/MyToken.tsscripts/deploy.tshardhat.config.ts(replace your generated one)
Replace 'MyToken' and 'MTK' with your token name and ticker symbol.
npx hardhat testYou don’t need to compile first—
hardhat testcompiles automatically. (Optional:npx hardhat compileto check build only.)
npx hardhat run scripts/deploy.ts --network sepoliaCopy the deployed address from the console output.
# Pass the exact constructor arg (1,000,000 * 10^18 in this example)
npx hardhat verify --network sepolia <DEPLOYED_ADDRESS> 1000000000000000000000000MyToken.sol: ERC-20 with fixed supply + ERC20Permit (EIP-2612).- Test: Verifies the deployer receives the entire initial supply.
- Deploy script: Ethers v6 style (
waitForDeployment,getAddress).
INSUFFICIENT_FUNDSon deploy → get Sepolia ETH from a faucet.- No account provided / bad key → ensure
PRIVATE_KEYin.envincludes the0xprefix. - RPC errors → verify
SEPOLIA_RPC_URLis a valid HTTPS endpoint (Alchemy/Infura/etc.) and that Sepolia is enabled in your provider project. - Verify fails → constructor arg must match exactly; ensure Solidity version & optimizer settings in
hardhat.config.tsmatch your contract. Try again after ~30–60s.
Add to package.json:
{
"scripts": {
"build": "hardhat compile",
"test": "hardhat test",
"deploy:sepolia": "hardhat run scripts/deploy.ts --network sepolia",
"verify:sepolia": "hardhat verify --network sepolia"
}
}Usage:
npm run deploy:sepolia
npm run verify:sepolia -- <DEPLOYED_ADDRESS> 1000000000000000000000000Once you’re comfortable on Sepolia, you can deploy to Ethereum mainnet (or another L1/L2).
- Ensure enough ETH for gas.
MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY # or Alchemy/QuickNode
PRIVATE_KEY=0xYOUR_MAINNET_PRIVATE_KEY
ETHERSCAN_API_KEY=YOUR_ETHERSCAN_KEYnetworks: {
sepolia: { /* ... */ },
mainnet: {
url: process.env.MAINNET_RPC_URL || "",
chainId: 1,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
},
},npx hardhat run scripts/deploy.ts --network mainnetnpx hardhat verify --network mainnet <DEPLOYED_ADDRESS> 1000000000000000000000000Production tips
- Triple-check constructor args; supply/config are immutable once live.
- Gas can spike—deploy during low-fee windows.
- Consider a security review if this token will hold value.
- Everything on mainnet is permanent and public.