# Comprendre le Gas sur Ethereum — Comment Ça Marche Vraiment
Le gas confond tous les débutants. "Pourquoi ai-je payé $50 pour une transaction échouée ?" "Quelle est la différence entre gas price et gas limit ?" Ce guide explique le gas Ethereum depuis les principes de base.
Qu'est-ce que le Gas ?
Le gas est l'effort computationnel requis pour exécuter des opérations sur Ethereum.
Pensez-y comme l'essence pour votre voiture :
- Unités de gas = litres d'essence
- Prix du gas = prix par litre
- Coût total = unités × prix
Sur Ethereum :
- Unités de gas = étapes computationnelles
- Prix du gas = ETH par unité
- Coût total = gas utilisé × prix du gas
Pourquoi le Gas Existe-t-il ?
Deux raisons :
1. Prévenir le Spam
Sans gas, quelqu'un pourrait déployer ceci :
contract InfiniteLoop {
function attack() public {
while (true) {} // Gèlerait le réseau pour toujours
}
}
Le gas limite le temps d'exécution. Quand le gas s'épuise, l'exécution s'arrête.
2. Compenser les Validateurs
Les validateurs incluent votre transaction dans un bloc. Ils méritent un paiement pour :
- Exécuter le calcul
- Stocker les changements d'état
- Coûts de bande passante
Unités de Gas vs ETH
Les unités de gas mesurent le travail computationnel. Elles sont les mêmes quel que soit le prix de l'ETH.
Exemples d'opérations :
| Opération | Coût Gas |
|-----------|----------|
| Addition (a + b) | 3 |
| Multiplication | 5 |
| SSTORE (écriture storage) | 20 000 (cold) / 5 000 (warm) |
| SLOAD (lecture storage) | 2 100 (cold) / 100 (warm) |
| Transfert ETH | 21 000 |
| Déployer contrat | 32 000 + taille code |
Un simple transfer() utilise ~21 000 gas. Un swap DeFi complexe peut utiliser 200 000 gas.
EIP-1559 : La Mise à Jour London (2021)
Avant EIP-1559, vous définissiez un seul prix de gas. Maintenant il y a DEUX composants :
Frais Total = (Base Fee + Priority Fee) × Gas Utilisé
Base Fee
- Déterminée par la demande réseau, pas les utilisateurs
- Brûlée (retirée de la circulation)
- S'ajuste à chaque bloc selon la congestion :
- Bloc > 50% plein → base fee augmente de 12,5%
- Bloc < 50% plein → base fee diminue de 12,5%
Actuellement ~10-50 gwei selon la congestion.
Priority Fee (Pourboire)
- Définie par les utilisateurs pour inciter les validateurs
- Payée aux validateurs (pas brûlée)
- Pourboire plus élevé = inclusion plus rapide
Typiquement 1-2 gwei en temps normal.
Gas Limit vs Gas Utilisé
Gas Limit
Le maximum de gas que vous autorisez.
// Vous définissez : Gas Limit = 100 000
// L'exécution réelle utilise : 67 000
// Vous payez pour : 67 000 (pas 100 000)
// Remboursement : 33 000 worth de gas
Si l'exécution nécessite 120 000 mais votre limite est 100 000 :
- La transaction échoue (revert)
- Vous payez quand même pour les 100 000 gas tentés
- 🔥 C'est pourquoi les transactions échouées coûtent de l'argent
Bonne pratique : Définissez la limite 20-50% plus haute que l'estimation.
Gas Utilisé
Le montant réel consommé.
function transfer(address to, uint256 amount) external {
balances[msg.sender] -= amount; // SSTORE : 5 000 gas
balances[to] += amount; // SSTORE : 20 000 gas
// Total : ~25 000 + overhead
}
Vous ne payez que pour le gas réellement utilisé (jusqu'à votre limite).
Calculer le Coût d'une Transaction
Avant EIP-1559 (Legacy)
Coût = Gas Utilisé × Prix Gas
Exemple :
100 000 gas × 50 gwei = 5 000 000 gwei = 0,005 ETH
Après EIP-1559
Max Fee Per Gas = Base Fee + Max Priority Fee
Coût = Gas Utilisé × (Base Fee + Priority Fee)
Exemple :
Base Fee : 30 gwei
Priority Fee : 2 gwei
Gas Utilisé : 100 000
Coût = 100 000 × 32 gwei = 3 200 000 gwei = 0,0032 ETH
Définir les Frais dans les Wallets
Vous spécifiez :
- Max Fee Per Gas : Maximum absolu que vous paierez (ex: 100 gwei)
- Max Priority Fee : Pourboire maximum au validateur (ex: 2 gwei)
Si la base fee est 30 gwei et vous définissez max fee 100 gwei :
- Frais réels = 30 + 2 = 32 gwei
- Vous économisez 68 gwei par unité de gas
- Le wallet rembourse la différence
Block Gas Limit
Chaque bloc a un gas total maximum (actuellement 30 millions).
Block Gas Limit : 30 000 000
Transaction Moyenne : 100 000 gas
Transactions par bloc : ~300
Si la demande dépasse l'espace du bloc → base fee augmente → moins de transactions → congestion se résorbe.
Coûts des Opérations Courantes
Opérations Storage (Plus Chères)
contract Storage {
uint256 public value; // Première écriture : 20 000 gas
function set(uint256 newValue) external {
value = newValue; // Mise à jour : 5 000 gas
}
function get() external view returns (uint256) {
return value; // Lecture : 2 100 gas (première fois), 100 gas (suivantes)
}
}
Accès cold (première fois dans une transaction) : coûteux
Accès warm (fois suivantes) : pas cher
Transfert ERC-20
function transfer(address to, uint256 amount) external {
// 2 opérations SSTORE + overhead
// Total : ~45 000-65 000 gas
}
Swap Uniswap
router.swapExactTokensForTokens(...);
// Plusieurs contrats, maths complexes, mises à jour storage
// Total : ~150 000-250 000 gas
Mint NFT
nft.mint();
// Créer nouveau token, mettre à jour mappings, émettre event
// Total : ~50 000-150 000 gas
Comment Estimer le Gas
Méthode 1 : Simulation Wallet
Les wallets (MetaMask, Rainbow) simulent la transaction et estiment le gas.
Méthode 2 : eth_estimateGas RPC
const provider = new ethers.JsonRpcProvider("https://...");
const gasEstimate = await provider.estimateGas({
to: contractAddress,
data: encodedFunctionCall,
from: userAddress,
});
console.log(Estimated gas: ${gasEstimate});
Méthode 3 : Rapports Gas Foundry
forge test --gas-report
| Function | Gas |
|-----------|---------|
| mint | 51,234 |
| transfer | 34,567 |
Comment Économiser du Gas
1. Utiliser calldata au Lieu de memory
// ❌ Coûteux
function process(uint256[] memory data) external {
// Copie en mémoire : coûte du gas
}
// ✅ Pas cher
function process(uint256[] calldata data) external {
// Lit directement depuis les données de transaction
}
Économies : ~50 gas par élément du tableau.
2. Packer les Variables de Storage
// ❌ Utilise 3 slots de storage (3 × 20 000 gas)
contract Inefficient {
uint128 a;
uint256 b;
uint128 c;
}
// ✅ Utilise 2 slots de storage (2 × 20 000 gas)
contract Efficient {
uint128 a;
uint128 c;
uint256 b;
}
Chaque slot fait 32 bytes. Packez les petites variables ensemble.
3. Utiliser les Events au Lieu du Storage
// ❌ Storage : 20 000 gas
mapping(uint256 => string) public messages;
function log(uint256 id, string memory message) external {
messages[id] = message;
}
// ✅ Events : ~375 gas
event Message(uint256 indexed id, string message);
function log(uint256 id, string memory message) external {
emit Message(id, message);
}
Utilisez les events pour les données que vous n'avez pas besoin d'interroger on-chain.
4. Opérations par Lots
// ❌ Plusieurs transactions
token.transfer(user1, 100);
token.transfer(user2, 100);
token.transfer(user3, 100);
// 3 × 21 000 coût de base = 63 000 gas gaspillé
// ✅ Transaction unique
token.batchTransfer([user1, user2, user3], [100, 100, 100]);
// 1 × 21 000 coût de base
5. Utiliser unchecked pour les Maths Sûres
// ❌ Vérifications d'overflow à chaque opération
for (uint i = 0; i < 1000; i++) {
// i++ inclut vérification d'overflow
}
// ✅ Saute les vérifications quand l'overflow est impossible
for (uint i = 0; i < 1000;) {
// ... logique
unchecked { i++; }
}
Économies : ~20 gas par opération.
6. Court-Circuiter les Conditionnels
// ❌ Évalue les deux conditions
if (expensiveCheck() && cheapCheck()) {}
// ✅ Court-circuite si la première est fausse
if (cheapCheck() && expensiveCheck()) {}
maxFeePerGas vs maxPriorityFeePerGas
Lors de l'envoi d'une transaction :
await contract.mint({
maxFeePerGas: ethers.parseUnits("100", "gwei"), // Max total
maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"), // Max pourboire
});
Scénario 1 : Congestion Normale
Base Fee : 30 gwei
Votre Max Fee : 100 gwei
Votre Max Priority : 2 gwei
Frais Réels Payés : 30 + 2 = 32 gwei
Remboursement : 68 gwei par unité de gas
Scénario 2 : Haute Congestion
Base Fee : 95 gwei
Votre Max Fee : 100 gwei
Votre Max Priority : 2 gwei
Frais Réels Payés : 95 + 2 = 97 gwei
Remboursement : 3 gwei par unité de gas
Scénario 3 : Congestion Extrême
Base Fee : 120 gwei
Votre Max Fee : 100 gwei
Résultat : Transaction NON incluse (max fee trop bas)
Gas Tokens (Obsolète)
Avant EIP-1559, les "gas tokens" (CHI, GST2) exploitaient les remboursements de storage pour économiser du gas. Ils sont obsolètes maintenant.
Solutions Layer 2
Les L2s (Arbitrum, Optimism, Base) réduisent le gas de 10-100x :
| Réseau | Coût Transfert |
|---------|---------------|
| Ethereum | 0,001 ETH ($3) |
| Arbitrum | 0,0001 ETH ($0,30) |
| Optimism | 0,0001 ETH ($0,30) |
| Base | 0,00005 ETH ($0,15) |
Même code, exécution moins chère.
Questions Courantes
"Pourquoi ma transaction échouée a coûté du gas ?"
Les validateurs ont quand même exécuté votre code (jusqu'à ce qu'il échoue). Ils méritent un paiement pour ce travail.
"Pourquoi le gas est si élevé maintenant ?"
Haute demande → blocs pleins → base fee augmente. Vérifiez etherscan.io/gastracker pour les prix actuels.
"Devrais-je définir un max fee très élevé ?"
Pas besoin. Vous ne payez que baseFee + priorityFee, l'excès est remboursé. Mais définissez-le assez haut pour couvrir les augmentations potentielles de base fee.
"Comment obtenir une inclusion instantanée ?"
Définissez un priority fee élevé (5-10 gwei). Les validateurs priorisent les pourboires élevés.
Résumé
- Unités de gas = travail computationnel (constant)
- Prix du gas = coût ETH par unité (variable)
- Base fee = brûlée, s'ajuste avec la congestion
- Priority fee = pourboire aux validateurs
- Gas limit = max que vous autorisez (vous êtes remboursé du non-utilisé)
- Gas utilisé = montant réel consommé
Astuce pro : Utilisez gwei.io ou ultrasound.money pour vérifier les prix de gas actuels avant de transacter.
Suivant : Apprenez les techniques d'optimisation du gas pour écrire des smart contracts efficaces !