Introduction
En 2026, Hardhat reste l'outil de référence pour développer, tester et déployer des smart contracts Ethereum. Contrairement à Truffle, qui est plus rigide, Hardhat offre une flexibilité exceptionnelle grâce à ses plugins, son REPL intégré et son support natif des forks de chaînes. Ce tutoriel intermédiaire vous guide pas à pas pour créer un projet complet : de l'installation à un déploiement sur Sepolia (testnet Ethereum).
Pourquoi Hardhat ? Il accélère le debugging avec des traces détaillées, intègre Mocha/Chai pour des tests robustes et gère les déploiements multi-réseaux via Ethers.js. Imaginez comme un atelier de mécanicien : tous les outils sous la main pour assembler un moteur Solidity sans friction. À la fin, vous aurez un Greeter contract fonctionnel, testé et déployé. Prêt à plonger dans le Web3 ? (142 mots)
Prérequis
- Node.js 20+ et npm/yarn/pnpm
- Connaissances de base en Solidity (variables, fonctions, événements)
- Un compte MetaMask avec ETH sur Sepolia (via faucet)
- Git pour versionner le projet
- Éditeur comme VS Code avec extension Solidity
Initialiser le projet Hardhat
mkdir hardhat-greeter && cd hardhat-greeter
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox @nomicfoundation/hardhat-verify
npx hardhat init
# Choisir 'Create a JavaScript project' puis 'Yes, with a sample project'Cette commande crée un dossier projet, initialise package.json et installe Hardhat avec son toolbox (compilateur Solidity, tests, ethers.js, verification). L'init génère une structure boilerplate : contracts/, scripts/, test/, hardhat.config.js. Évitez les versions globales de Hardhat pour isoler les dépendances.
Comprendre la structure générée
Après init, votre projet a :
- contracts/ : Smart contracts Solidity.
- scripts/ : Scripts JS pour déploiement.
- test/ : Tests unitaires en Mocha/Chai.
- hardhat.config.js : Configuration centrale (réseaux, Solidity version).
C'est comme une maison préfabriquée : prête à customiser. Nous allons remplacer le sample par un Greeter personnalisé.
Configurer hardhat.config.js
require('@nomicfoundation/hardhat-toolbox');
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
version: '0.8.28',
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
networks: {
hardhat: {},
sepolia: {
url: 'https://sepolia.infura.io/v3/VOTRE_CLE_INFURA',
accounts: ['0xVOTRE_PRIVATE_KEY']
}
},
etherscan: {
apiKey: {
sepolia: 'VOTRE_CLE_ETHERSCAN'
}
}
};Cette config définit Solidity 0.8.28 avec optimisation (réduit gas). Ajoute Sepolia via Infura (remplacez par vos clés). Le réseau 'hardhat' simule une blockchain locale pour tests. Remplacez les placeholders par vos vraies clés (Infura/Etherscan gratuites). Piège : Oublier l'optimizer augmente les coûts gas en prod.
Créer le smart contract Greeter
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract Greeter {
string private _greeting;
constructor(string memory greeting) {
_greeting = greeting;
}
function greet() public view returns (string memory) {
return _greeting;
}
function setGreeting(string memory greeting) public {
_greeting = greeting;
}
}Ce contrat stocke un message en private, expose getter 'greet()' et setter modifiable. Utilise ^0.8.28 pour sécurité (SafeMath auto). Constructor initialise. Exemple concret : deploy avec 'Hello Hardhat!' et update vers 'Bonjour 2026'. Copiez-collez directement.
Compiler le contrat
Hardhat compile automatiquement les .sol en artifacts (ABI + bytecode). Exécutez npx hardhat compile pour vérifier. Output dans artifacts/ et cache/. Analogy : Comme un compilateur C vers machine code, mais pour EVM.
Écrire les tests unitaires
const { expect } = require('chai');
const { ethers } = require('hardhat');
describe('Greeter', function () {
it('Should return the greeting provided in constructor', async function () {
const Greeter = await ethers.getContractFactory('Greeter');
const greeter = await Greeter.deploy('Hello Hardhat!');
await greeter.waitForDeployment();
expect(await greeter.greet()).to.equal('Hello Hardhat!');
});
it('Should emit event on setGreeting', async function () {
const Greeter = await ethers.getContractFactory('Greeter');
const greeter = await Greeter.deploy('Hello Hardhat!');
await greeter.waitForDeployment();
await expect(greeter.setGreeting('Hola 2026'))
.to.emit(greeter, 'GreetingUpdated') // Ajoutez event si besoin
.to.not.be.reverted;
});
});Tests vérifient constructor et setter avec expect Chai. Utilise ethers pour factory/deploy. Deuxième test check non-revert. Lancez avec npx hardhat test. Ajoutez un event GreetingUpdated pour full coverage. Piège : Oublier waitForDeployment() cause timeouts.
Script de déploiement
const hre = require('hardhat');
async function main() {
const Greeter = await hre.ethers.getContractFactory('Greeter');
const greeter = await Greeter.deploy('Hello Hardhat 2026!');
await greeter.waitForDeployment();
console.log('Greeter deployed to:', await greeter.getAddress());
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});Script deploy via ethers factory, log l'adresse. hre accède à Hardhat Runtime Env. Copiez dans scripts/, lancez npx hardhat run scripts/deploy.js --network hardhat. Pour Sepolia : --network sepolia. Gestion erreurs avec catch.
Déployer et vérifier
Local : npx hardhat run scripts/deploy.js
Sepolia : npx hardhat run scripts/deploy.js --network sepolia
Vérifier : npx hardhat verify --network sepolia ADRESSE_CONTRAT "Hello Hardhat 2026!"
Console affiche l'adresse. Vérification Etherscan rend le contrat public (source code).
Forker une chaîne pour tests avancés
networks: {
hardhat: {
forking: {
url: 'https://eth-mainnet.g.alchemy.com/v2/VOTRE_CLE_ALCHEMY',
blockNumber: 20000000
}
}
},Ajoutez ceci à hardhat.config.js pour forker Mainnet (Alchemy gratuit). Tests sur état réel sans gas. Ex: Impersonate un whale pour transfers massifs. Relancez npx hardhat node pour REPL. Piège : BlockNumber récent évite forks obsolètes.
Bonnes pratiques
- Optimisez Solidity : Activez optimizer (runs:200+) pour gas <10%.
- Tests coverage : Ajoutez
npm i -D hardhat-gas-reporter solidity-coverageet intégrez dans config. - Envs sécurisés : Utilisez
dotenvpour clés (.env+require('dotenv').config()). - Gas reporting :
hardhat.config.jsavec gasReporter pour benchmarks. - Multi-compiler : Supportez 0.8.x + 0.5.x si legacy.
Erreurs courantes à éviter
- Private key exposée : Jamais en dur dans config ; utilisez
process.env.PRIVATE_KEY. - Version Solidity mismatch : pragma ^0.8.28 = config 0.8.28, sinon erreur compile.
- Pas de waitForDeployment() : Tests async échouent sans ça (post-London fork).
- Réseau non-fundé : Vérifiez faucet Sepolia ; testez local d'abord.
Pour aller plus loin
- Docs officielles : Hardhat Book
- Plugins avancés : Foundry pour tests plus rapides, Tenderly pour debugging.
- Formations : Découvrez nos formations Learni sur Ethereum
- Repo exemple : Forkez ce tuto sur GitHub pour expérimenter.