Hardhat development for EVM chains including Celo. Use when setting up Hardhat projects, writing Solidity contracts, compiling, testing, deploying, or verifying contracts with Hardhat.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Hardhat development for EVM chains including Celo. Use when setting up Hardhat projects, writing Solidity contracts, compiling, testing, deploying, or verifying contracts with Hardhat.
license
Apache-2.0
metadata
{"author":"celo-org","version":"1.0.0"}
Hardhat Development for EVM Chains
This skill covers Hardhat setup and development for EVM-compatible chains with emphasis on Celo.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, Ownable {
constructor() ERC20("MyToken", "MTK") Ownable(msg.sender) {
_mint(msg.sender, 1000000 * 10 ** decimals());
}
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
}
Compilation
# Compile all contracts
npx hardhat compile
# Clean and recompile
npx hardhat clean && npx hardhat compile
Testing
Test File Structure
// test/MyContract.test.tsimport { expect } from"chai";
import { ethers } from"hardhat";
import { MyContract } from"../typechain-types";
describe("MyContract", function () {
letcontract: MyContract;
letowner: any;
letaddr1: any;
beforeEach(asyncfunction () {
[owner, addr1] = await ethers.getSigners();
constMyContract = await ethers.getContractFactory("MyContract");
contract = awaitMyContract.deploy("Initial Name");
await contract.waitForDeployment();
});
describe("Deployment", function () {
it("Should set the right name", asyncfunction () {
expect(await contract.name()).to.equal("Initial Name");
});
it("Should set the right owner", asyncfunction () {
expect(await contract.owner()).to.equal(owner.address);
});
});
describe("setName", function () {
it("Should allow owner to change name", asyncfunction () {
await contract.setName("New Name");
expect(await contract.name()).to.equal("New Name");
});
it("Should emit NameChanged event", asyncfunction () {
awaitexpect(contract.setName("New Name"))
.to.emit(contract, "NameChanged")
.withArgs("Initial Name", "New Name");
});
it("Should revert if non-owner tries to change name", asyncfunction () {
awaitexpect(
contract.connect(addr1).setName("Hacked")
).to.be.revertedWith("Not owner");
});
});
});
Running Tests
# Run all tests
npx hardhat test# Run specific test file
npx hardhat testtest/MyContract.test.ts
# Run with gas reporting
REPORT_GAS=true npx hardhat test# Run with coverage
npx hardhat coverage
# Deploy to local Hardhat network
npx hardhat run scripts/deploy.ts
# Deploy to Celo Sepolia testnet
npx hardhat run scripts/deploy.ts --network celoSepolia
# Deploy to Celo Mainnet
npx hardhat run scripts/deploy.ts --network celo
Verification
Verify After Deployment
# Verify on Celo Sepolia
npx hardhat verify --network celoSepolia <CONTRACT_ADDRESS> "Constructor Arg 1"# Verify on Celo Mainnet
npx hardhat verify --network celo <CONTRACT_ADDRESS> "Constructor Arg 1"