Introduction
En 2026, les tokens ERC-20 restent le standard dominant pour les cryptomonnaies fongibles sur Ethereum et ses layer-2. Ce tutoriel intermediate vous guide pas à pas pour créer un token ERC-20 personnalisé en Solidity 0.8.26, en utilisant les bibliothèques OpenZeppelin pour une sécurité optimale. Vous apprendrez à implémenter les fonctions essentielles (transfert, approbation), des extensions avancées (mint contrôlé, burn, pause d'urgence) et le déploiement sur un testnet via Remix IDE.
Pourquoi ce contrat ? Contrairement à un ERC-20 basique, le nôtre inclut des garde-fous comme l'ownership pour éviter les hacks courants (reentrancy, overflow). Imaginez-le comme une maison fortifiée : fondations solides (ERC-20 core), serrures supplémentaires (Ownable, Pausable). À la fin, vous aurez un token déployé, testable et prêt pour Uniswap ou un DEX. Temps estimé : 30 minutes. Prêt à mint votre premier million de tokens ?
Prérequis
- Connaissances de base en Solidity (variables, modifiers, events)
- Compte MetaMask avec ETH sur Sepolia testnet (faucet : sepoliafaucet.com)
- Remix IDE (remix.ethereum.org) ouvert dans votre navigateur
- Familiarité avec les standards ERC-20 (totalSupply, balanceOf, transfer)
Squelette ERC-20 basique
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyTokenBasic is ERC20 {
constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
_mint(msg.sender, initialSupply * 10 ** decimals());
}
}Ce contrat hérite d'ERC20 d'OpenZeppelin, implémentant transfer, approve, balanceOf automatiquement. Le constructeur mint un supply initial au déployeur. Piège : Oublier *10**decimals() sous-estime les unités (18 par défaut). Copiez en Remix, compilez avec Solidity 0.8.26.
Ajout de l'ownership
Pour un contrôle admin (renoncer ownership, transfer), étendons avec Ownable. Cela évite les contrats figés post-déploiement. OpenZeppelin gère les modifiers onlyOwner. Testez en console Remix : deploy avec 1000000, vérifiez balanceOf(deployer).
ERC-20 avec Ownable
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyTokenOwnable is ERC20, Ownable {
constructor(uint256 initialSupply) ERC20("MyToken", "MTK") Ownable(msg.sender) {
_mint(msg.sender, initialSupply * 10 ** decimals());
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}Ownable ajoute onlyOwner et owner(). Nouvelle fonction mint pour émettre plus de tokens. Sécurité : mint restreint au owner, évitant l'inflation anarchique. Déployez, appelez mint(ami, 1000e18) depuis owner.
Gestion des urgences avec Pausable
Les hacks comme Ronin (2022) montrent l'utilité de pause. Pausable bloque transfers en urgence. Combinez avec whenNotPaused modifier. Idéal pour audits post-lancement.
ERC-20 pausable et burnable
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
contract MyTokenAdvanced is ERC20, ERC20Burnable, ERC20Pausable, Ownable {
constructor(uint256 initialSupply) ERC20("MyToken", "MTK") Ownable(msg.sender) {
_mint(msg.sender, initialSupply * 10 ** decimals());
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function _update(address from, address to, uint256 amount) internal override(ERC20, ERC20Pausable) {
super._update(from, to, amount);
}
}Héritage multiple : Burnable (burn self), Pausable (pause/unpause). Override _update pour intégrer pause aux transfers. Test : pause(), tentez transfer (revert), unpause(). Burn réduit supply définitivement.
Script de test en Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "./MyTokenAdvanced.sol";
contract MyTokenTest {
MyTokenAdvanced public token;
constructor() {
token = new MyTokenAdvanced(1000000);
}
function testTransfer(address to, uint256 amount) public {
token.transfer(to, amount);
}
function testMint(address to, uint256 amount) public {
token.mint(to, amount);
}
}Contrat test pour valider sans JS. Déployez, appelez testTransfer(0x..., 1e18). Vérifiez events/logs en Remix. Utile pour simuler interactions avant déploiement mainnet.
Déploiement sur Sepolia
Étapes Remix :
- Copiez MyTokenAdvanced.sol dans un nouveau workspace.
- Compilez (Solidity 0.8.26, auto-import OpenZeppelin).
- Deploy & Run > Injected Provider (MetaMask Sepolia).
- Déployez avec initialSupply=1000000.
- Notez l'adresse contrat, vérifiez sur Sepolia Etherscan.
Ajoutez liquidity sur Uniswap testnet pour trading.
Vérification ABI pour frontend
[
{
"inputs": [
{"internalType": "address", "name": "to", "type": "address"},
{"internalType": "uint256", "name": "amount", "type": "uint256"}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "pause",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
"stateMutability": "view",
"type": "function"
}
]Extrait ABI pour intégration Web3.js/ethers.js. Copiez l'ABI complet depuis Remix (Compilation Details > ABI). Utilisez pour appeler mint depuis React/Vue.
Bonnes pratiques
- Utilisez toujours OpenZeppelin : Audité, protège contre reentrancy/overflow (SafeMath intégré depuis 0.8).
- Renoncez ownership post-mint : Appelez renounceOwnership() pour décentralisation vraie.
- Testez exhaustivement : Foundry/Hardhat pour fuzzing, Slither pour audits statiques.
- Gas optimization : Immutables pour constantes, <0.8.26 évite checks coûteux.
- Documentation NatSpec : Ajoutez /// @notice pour Etherscan vérification.
Erreurs courantes à éviter
- Oubli decimals() : Mint 1e6 donne 1e6 wei, pas millions de tokens.
- Héritage sans override : _update manquant casse Pausable (revert sur transfer).
- Mint illimité sans cap : Ajoutez maxSupply pour éviter hyperinflation.
- Déploiement sans testnet : Perte gas mainnet ; toujours Sepolia d'abord.
Pour aller plus loin
Maîtrisez les hooks ERC-20 (transfer hooks pour fees). Étudiez ERC-4626 (vaults). Ressources :
Découvrez nos formations Learni sur Solidity & DeFi pour pro-level : audits, L2 deployment, flashloans.