Optimiser la consommation en gas (gaz) d’un smart contract Ethereum

0

Le gaz (gas en anglais) est indispensable sur le réseau Ethereum pour exécuter tout contrat. Même si au premier abord, devoir payer pour exécuter du code peut sembler bizarre, cela est indispensable pour deux raisons :

– une blockchain fonctionne comme un immense ordinateur dont chacun peut posséder une partie, et est rémunéré en contrepartie des calculs qu’il effectue (la validation des blocs, ce qu’on appelle le minage). Chaque transaction est validée par des milliers de nœuds du réseau, et c’est ce qui garantit la sécurité très importante du système.

– Pour pas qu’un utilisateur de  » l’ordinateur géant « que constitue la blockchain Ethereum puisse s’accaparer toutes les ressources de celui-ci, que ce soit volontairement ou par une erreur de code avec par exemple une boucle infinie, exécuter des fonctions a un coût qui augmente avec la consommation de ressources utilisées.

Pour conclure, on voit donc que ce carburant du réseau garantit sa sécurité et sa fiabilité. Ce qui est intéressant ici, c’est que pour sécuriser des données il est plus efficace d’ajouter des ordinateurs au réseau que d’acheter des systèmes complexes ou cher comme avec des données centralisées.

Il est donc très important, à chaque développement d’un smart contract, d’anticiper le fait que la quantité de gas (ETH) qu’il utilisera sera proportionnelle aux nombres de fonctions qu’il exécute.
Coder proprement ne devient donc plus juste une rigueur méthodologique, mais bien un pré requis pour garantir l’efficacité de son application.

Imaginez une application très utilisée, qui se vend bien, dont les utilisateurs sont contents, mais qui a été mal pensée et qui consomme beaucoup de ressources, elle serait assez rapidement sortie du marché par un concurrent qui a développé cette application avec un coût de fonctionnement beaucoup élevé.

Voyons maintenant deux types de données qui peuvent être optimisées, les struct et les uint

Au vu de ce qui est décrit ci dessus, il pourrait être tentant de bien spécifier pour chaque uint sa taille exacte en byte en utilisant uint8, uint16, … uint256 etc, mais c’est en fait parfaitement inutile car Solidity réserve dans tous les cas 256 bits de stockage pour un uint (au passage int et uint sont des alias de uint256). On ne gagnera donc pas de gas à utiliser un uint32 plutôt que uint8, sauf dans un cas très particulier qui est le type de donnée struct

La consommation de gas dans les structures (struct)

Struct est dans Solidity un type de variable particulier qui peut contenir plusieurs autres types de variables, c’est un lointain cousin d’un objet dans un autre langage de programmation plus classique.

Imaginons que nous souhaitons stocker pour une personne son nom, son âge, et son adresse Ethereum, on peut alors créer une structure ainsi :

    struct Personne{
        string Nom;
        uint Age;
        address Adresse;
    }

On pourra ensuite par exemple initialiser Michel qui a 34 ans et dont l’adresse ETH est « 0xca35… » ainsi :

Personne personne = Personne("Michel",34,"0xca35...");

Venons en à l’optimisation en gas, Solidity va automatiquement emboîter les uint à l’intérieur d’un struct, et il sera donc intéressant d’utiliser le plus petit sous type possible.

Reprenons l’exemple de notre struct Personne, nous allons ajouter aussi une variable pour le poids. On pourrait simplement ajouter uint Poids; dans la déclaration, ce qui donnerait :

    struct Personne{
        string Nom;
        uint Age;
        uint Poids;
        address Adresse;
    }

Cependant, pour optimiser la consommation il serait plus intelligent de faire ainsi :

    struct Personne{
        string Nom;
        uint8 Age;
        uint8 Poids;
        address Adresse;
    }

Cela évitera de bloquer 2×256 bits pour des variables qui n’utiliseront jamais cet espace. Cela peut paraître minime, mais à l’échelle de milliers de transactions, ce peut être fondamental.

Enfin, il faut aussi regrouper ensemble les types pour en minimiser le coût, ce serait une mauvaise idée de faire :

    struct Personne{
        string Nom;
        uint8 Age;
        address Adresse;
        uint8 Poids;
    }

Toujours dans cette logique, il faut regrouper aussi les sous types, par exemple uint X; uint32 Y; uint32 Z; consommera moins que uint32 Z; uint X; uint32 Y;

Une fonction View ne consomme aucun gas

Un point important à retenir, est que toute fonction dont la visibilité est définie sur View ne consommera aucun gaz, et devra donc être privilégié pour lire des données sur la blockchain Ethereum. Celle-ci en effet ne crée pas de transaction et ne coûte rien. Attention cependant, une fonction view à l’intérieur d’une fonction qui coute du gaz (qui elle va créer une transaction) aura par contre un coût.

Ecrire dans la blockchain coûte très cher

A chaque fois que vous inscrivez des données dans la blockchain, elles seront répliqués dans l’ensemble des noeuds, c’est pour cela que l’opération la plus chère en gaz est de loin le fait d’y stocker des données. Il faut toujours faire en sorte de ne stocker que ce qui est indispensable.

Vous avez maintenant quelques bases pour réduire la consommation de vos contrats, il faudra toujours dans Solidity se laisser une phase d’optimisation de son code avant son passage en production, bien plus que dans n’importe quel autre langage, puisque rappelons le, un contrat ne peut plus être modifié une fois déployé sur la blockchain Ethereum.

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.