
Les 10 meilleures pratiques pour l'optimisation du gaz dans les contrats intelligents Ethereum
TechFlow SélectionTechFlow Sélection

Les 10 meilleures pratiques pour l'optimisation du gaz dans les contrats intelligents Ethereum
En suivant ces bonnes pratiques, les développeurs peuvent réduire la consommation de gaz des contrats intelligents, diminuer les coûts des transactions et créer des applications plus efficaces et plus conviviales pour les utilisateurs.
Rédaction : Certik
Les frais de gaz sur le réseau principal d'Ethereum ont toujours été un problème majeur, particulièrement prononcé lors des périodes de congestion du réseau. En période de pointe, les utilisateurs doivent souvent payer des frais de transaction très élevés. Par conséquent, l'optimisation des frais de gaz dès la phase de développement des contrats intelligents revêt une importance capitale. Optimiser la consommation de gaz permet non seulement de réduire efficacement les coûts de transaction, mais aussi d'améliorer l'efficacité des transactions, offrant ainsi aux utilisateurs une expérience blockchain plus économique et plus performante.
Cet article présente un aperçu du mécanisme des frais de gaz de la Machine Virtuelle Ethereum (EVM), des concepts fondamentaux liés à l’optimisation des frais de gaz, ainsi que les meilleures pratiques pour optimiser ces frais lors du développement de contrats intelligents. Nous espérons que ce contenu fournira inspiration et assistance pratique aux développeurs, tout en aidant les utilisateurs ordinaires à mieux comprendre le fonctionnement des frais de gaz sur l’EVM, afin de relever ensemble les défis de l’écosystème blockchain.
Présentation du mécanisme des frais de gaz de l’EVM
Dans les réseaux compatibles avec l’EVM, « le gaz » est l'unité mesurant la puissance de calcul nécessaire à l'exécution d'une opération spécifique.
Le schéma ci-dessous illustre l'architecture de l’EVM. Il montre que la consommation de gaz se divise en trois parties : l’exécution d’opérations, les appels de messages externes, et la lecture/écriture de la mémoire et du stockage.

Source : site officiel d'Ethereum [1]
Étant donné que chaque transaction nécessite des ressources informatiques, des frais sont facturés afin d'éviter les boucles infinies et les attaques par déni de service (DoS). Le coût requis pour finaliser une transaction est appelé « frais de gaz ».
Depuis l'entrée en vigueur de l'EIP-1559 (fork dur de Londres), les frais de gaz sont calculés selon la formule suivante :
Frais de gaz = unités de gaz utilisées * (frais de base + frais prioritaires)
Les frais de base sont brûlés, tandis que les frais prioritaires servent d'incitation pour encourager les validateurs à inclure la transaction dans la chaîne de blocs. En fixant des frais prioritaires plus élevés lors de l'envoi d'une transaction, on augmente la probabilité que celle-ci soit incluse dans le prochain bloc. Cela équivaut à un « pourboire » versé aux validateurs par l'utilisateur.
1. Comprendre l’optimisation du gaz dans l’EVM
Lorsqu'un contrat intelligent est compilé en Solidity, il est transformé en une série d'« opcodes », c'est-à-dire des codes d'opération.
Chaque opcode (par exemple, création d’un contrat, appel de message, accès au stockage du compte ou exécution d’une opération sur la machine virtuelle) a un coût en gaz défini, consigné dans le livre jaune d'Ethereum [2].

À la suite de plusieurs modifications via des EIP, certains coûts en gaz des opcodes ont été ajustés, ce qui peut entraîner des écarts par rapport au livre jaune. Pour obtenir les informations les plus récentes sur les coûts des opcodes, veuillez consulter cette page [3].
2. Concepts fondamentaux de l’optimisation du gaz
L'idée centrale de l’optimisation du gaz consiste à privilégier les opérations économiques en termes de coût sur les blockchains EVM, tout en évitant celles dont le coût en gaz est élevé.
Dans l’EVM, les opérations peu coûteuses incluent :
-
La lecture/écriture de variables en mémoire
-
La lecture de variables constantes et immuables
-
La lecture/écriture de variables locales
-
La lecture de variables calldata, telles que les tableaux ou structures calldata
-
Les appels de fonctions internes
Les opérations coûteuses incluent :
-
La lecture/écriture de variables d’état stockées dans le stockage du contrat
-
Les appels de fonctions externes
-
Les boucles
Meilleures pratiques pour l’optimisation des frais de gaz sur l’EVM
Sur la base des concepts décrits ci-dessus, nous avons établi une liste de bonnes pratiques d’optimisation des frais de gaz destinée à la communauté des développeurs. En suivant ces recommandations, les développeurs peuvent réduire la consommation de gaz de leurs contrats intelligents, diminuer les coûts de transaction et concevoir des applications plus efficaces et conviviales.
1. Réduire autant que possible l’utilisation du stockage
Dans Solidity, le storage (stockage) est une ressource limitée dont la consommation de gaz est bien supérieure à celle de la memory (mémoire). Chaque lecture ou écriture de données dans le stockage par un contrat intelligent entraîne des frais de gaz élevés.
Selon la définition du livre jaune d'Ethereum, les opérations de stockage coûtent plus de 100 fois plus cher que celles en mémoire. Par exemple, les instructions opcodes mload et mstore ne consomment que 3 unités de gaz, alors que même dans les conditions optimales, les opérations de stockage comme sload et sstore coûtent au minimum 100 unités.

Pour limiter l'utilisation du stockage, on peut :
-
Stocker les données non permanentes en mémoire
-
Réduire le nombre de modifications du stockage : en conservant les résultats intermédiaires en mémoire et en n’écrivant le résultat final dans le stockage qu’après avoir terminé tous les calculs.
2. Empaquetage des variables
Le nombre de slots de stockage (storage slots) utilisés par un contrat intelligent, ainsi que la manière dont les données sont représentées par le développeur, influencent fortement la consommation de gaz.
Le compilateur Solidity regroupe automatiquement les variables de stockage contiguës pendant la compilation, en utilisant des slots de stockage de 32 octets comme unité de base. L’empaquetage des variables consiste donc à organiser judicieusement les variables afin que plusieurs d'entre elles tiennent dans un seul slot de stockage.
À gauche, une implémentation peu efficace consommant 3 slots ; à droite, une implémentation plus efficace.

En ajustant ce détail, les développeurs peuvent économiser 20 000 unités de gaz (le stockage d’un slot inutilisé coûtant 20 000 gas), car désormais deux slots suffisent.
Comme chaque slot de stockage consomme du gaz, l’empaquetage des variables permet d’optimiser la consommation de gaz en réduisant le nombre total de slots nécessaires.
3. Optimiser les types de données
Une variable peut être représentée par différents types de données, mais chacun a un coût opérationnel différent. Choisir le type de données approprié contribue à optimiser la consommation de gaz.
Par exemple, en Solidity, les entiers peuvent être subdivisés en différentes tailles : uint8, uint16, uint32, etc. Étant donné que l’EVM effectue ses opérations par unités de 256 bits, utiliser uint8 oblige l’EVM à le convertir d’abord en uint256, ce qui engendre un coût supplémentaire en gaz.

La comparaison entre uint8 et uint256 dans le code illustré montre que la fonction UseUint() consomme 120 382 unités de gaz, contre 166 111 pour UseUInt8().
Individuellement, l'utilisation de uint256 s'avère donc moins coûteuse que uint8. Toutefois, cela change si l’on applique l’optimisation par empaquetage précédemment conseillée. Si quatre variables uint8 peuvent être empaquetées dans un seul slot de stockage, leur coût total de lecture/écriture devient inférieur à celui de quatre variables uint256. Ainsi, le contrat peut lire/écrire un slot unique et transférer les quatre variables uint8 en mémoire ou en stockage en une seule opération.
4. Préférer les variables de taille fixe aux variables dynamiques
Lorsque les données peuvent être contenues dans 32 octets, il est recommandé d'utiliser le type bytes32 plutôt que bytes ou strings. Généralement, les variables de taille fixe consomment moins de gaz que celles de taille variable. Si la longueur des octets est connue, privilégiez la taille minimale allant de bytes1 à bytes32.


5. Mappings et tableaux
Les listes de données en Solidity peuvent être représentées par deux types : les tableaux (Arrays) et les mappings (Mappings), ayant des syntaxes et structures très différentes.
Les mappings sont généralement plus efficaces et moins coûteux, mais les tableaux sont itérables et permettent l’empaquetage des types de données. Il est donc conseillé d’utiliser des mappings pour gérer les listes de données, sauf besoin d’itération ou d’optimisation par empaquetage.
6. Utiliser calldata au lieu de memory
Les variables déclarées comme paramètres de fonction peuvent être stockées dans calldata ou dans memory. La différence principale est que memory peut être modifiée par la fonction, alors que calldata est immuable.
Retenez cette règle : si un paramètre de fonction est en lecture seule, utilisez de préférence calldata plutôt que memory, afin d’éviter une copie inutile depuis calldata vers memory.
Exemple 1 : utilisation de memory

Avec le mot-clé memory, les valeurs du tableau sont copiées depuis le calldata encodé vers la mémoire lors du décodage ABI. Ce bloc de code coûte 3 694 unités de gaz.
Exemple 2 : utilisation de calldata

Lorsqu’on lit directement depuis calldata, on évite l'étape intermédiaire de mémoire. Cette optimisation réduit le coût à seulement 2 413 unités de gaz, soit une amélioration d’efficacité de 35 %.
7. Utiliser autant que possible les mots-clés Constant/Immutable
Les variables constantes ou immuables ne sont pas stockées dans le stockage du contrat. Elles sont calculées à la compilation et intégrées directement au bytecode du contrat. Leur accès est donc beaucoup moins coûteux que celui du stockage. Il est fortement recommandé d’utiliser les mots-clés Constant ou Immutable lorsque possible.
8. Utiliser Unchecked lorsque les dépassements sont impossibles
Lorsque le développeur est certain qu'une opération arithmétique ne provoquera ni dépassement (overflow) ni débordement négatif (underflow), il peut utiliser le mot-clé unchecked introduit dans Solidity v0.8.0, évitant ainsi les vérifications superflues et réduisant les frais de gaz.
Dans l’exemple ci-dessous, la condition i<length garantit que la variable i ne dépassera jamais sa limite. Ici, length est défini comme uint256, donc la valeur maximale de i est max(uint)-1. Incrémenter i dans un bloc unchecked est donc sûr et plus économique en gaz.

Par ailleurs, à partir de la version 0.8.0, la bibliothèque SafeMath n’est plus nécessaire, car le compilateur intègre nativement la protection contre les dépassements.
9. Optimiser les modificateurs
Le code des modificateurs est intégré directement dans les fonctions modifiées. À chaque utilisation, son code est copié, augmentant la taille du bytecode et la consommation de gaz. Voici une méthode pour optimiser les frais de gaz liés aux modificateurs :
Avant optimisation :

Après optimisation :

Dans cet exemple, la logique a été refactorisée en une fonction interne _checkOwner(), réutilisable dans le modificateur. Cela réduit la taille du bytecode et diminue les frais de gaz.
10. Optimisation par court-circuit
Pour les opérateurs || et &&, l’évaluation logique suit un principe de court-circuit : si la première condition détermine déjà le résultat de l’expression, la deuxième n’est pas évaluée.
Pour optimiser la consommation de gaz, placez les conditions peu coûteuses en premier, afin d’éviter potentiellement des calculs plus lourds.
Recommandations générales complémentaires
1. Supprimer le code inutilisé
Il est recommandé de supprimer toute fonction ou variable inutilisée dans le contrat. C’est la méthode la plus directe pour réduire les coûts de déploiement et maintenir un contrat compact.
Voici quelques suggestions utiles :
Utilisez les algorithmes les plus efficaces possibles. Si certains résultats de calcul sont directement utilisés dans le contrat, supprimez les étapes redondantes. En somme, tout calcul inutilisé doit être éliminé.
Sur Ethereum, les développeurs reçoivent une récompense en gaz lorsqu’ils libèrent de l’espace de stockage. Si une variable n’est plus nécessaire, utilisez le mot-clé delete ou réinitialisez-la à sa valeur par défaut.
Optimisation des boucles : évitez les boucles coûteuses, fusionnez-les si possible, et sortez les calculs répétés du corps de la boucle.
2. Utiliser des contrats précompilés
Les contrats précompilés offrent des fonctions complexes telles que le chiffrement ou le hachage. Leur code n’est pas exécuté sur l’EVM, mais localement sur les nœuds clients, ce qui réduit la consommation de gaz. Leur utilisation diminue la charge de calcul requise par les contrats intelligents.
Des exemples incluent l'algorithme ECDSA (Elliptic Curve Digital Signature Algorithm) ou le hachage SHA2-256. En utilisant ces contrats précompilés, les développeurs abaissent les coûts de gaz et améliorent l’efficacité de leurs applications.
Pour la liste complète des contrats précompilés supportés par Ethereum, consultez ici [4].
3. Utiliser l’assemblage en ligne (inline assembly)
L’assemblage en ligne permet aux développeurs d’écrire du code bas niveau, hautement efficace, exécutable directement par l’EVM, sans passer par des opcodes Solidity coûteux. Il offre également un contrôle plus précis sur l’utilisation de la mémoire et du stockage, réduisant encore davantage les frais de gaz. De plus, il permet d’effectuer certaines opérations complexes difficiles à réaliser uniquement en Solidity, offrant ainsi plus de flexibilité pour optimiser la consommation de gaz.
Voici un exemple montrant comment l’assemblage en ligne permet d’économiser du gaz :

Comme indiqué dans l’image, la deuxième implémentation utilisant l’assemblage en ligne est nettement plus efficace en gaz que l’usage standard.
Toutefois, l’assemblage en ligne comporte des risques et peut facilement conduire à des erreurs. Son usage doit donc être prudent et réservé aux développeurs expérimentés.
4. Adopter des solutions Layer 2
L’utilisation de solutions Layer 2 permet de réduire la quantité de données devant être stockées et calculées sur la chaîne principale d’Ethereum.
Des solutions telles que les rollups, les sidechains et les canaux d’état déchargent le traitement des transactions de la chaîne principale, rendant les transactions plus rapides et moins chères.
En regroupant de nombreuses transactions, ces solutions diminuent le volume des transactions sur la chaîne, abaissant ainsi les frais de gaz. Elles améliorent également l’évolutivité d’Ethereum, permettant à davantage d’utilisateurs et d’applications de participer au réseau sans provoquer de congestion.
5. Utiliser des outils et bibliothèques d’optimisation
Plusieurs outils d’optimisation sont disponibles, tels que l’optimiseur du compilateur solc, l’optimiseur de construction de Truffle ou le compilateur Solidity de Remix.

Ces outils aident à minimiser la taille du bytecode, suppriment le code inutile et réduisent le nombre d’opérations nécessaires à l’exécution du contrat. Associés à des bibliothèques spécialisées comme « solmate », ils permettent aux développeurs de réduire efficacement les coûts de gaz et d’améliorer la performance de leurs contrats intelligents.
Conclusion
L’optimisation de la consommation de gaz est une étape cruciale pour les développeurs, permettant de minimiser les coûts de transaction et d’améliorer l’efficacité des contrats intelligents sur les réseaux compatibles EVM. En privilégiant les opérations économiques, en limitant l’utilisation du stockage, en exploitant l’assemblage en ligne et en suivant les autres bonnes pratiques exposées ici, les développeurs peuvent significativement réduire la consommation de gaz de leurs contrats.
Cependant, il est essentiel de souligner qu’au cours de l’optimisation, les développeurs doivent agir avec prudence afin de ne pas introduire de vulnérabilités de sécurité. L’optimisation du code et la réduction des frais de gaz ne doivent jamais compromettre la sécurité intrinsèque des contrats intelligents.
[1] : https://ethereum.org/en/developers/docs/gas/
[2] : https://ethereum.github.io/yellowpaper/paper.pdf
[3] : https://www.evm.codes/
[4] : https://www.evm.codes/precompiled
Bienvenue dans la communauté officielle TechFlow
Groupe Telegram :https://t.me/TechFlowDaily
Compte Twitter officiel :https://x.com/TechFlowPost
Compte Twitter anglais :https://x.com/BlockFlow_News














