Tutoriel Solidity : Optimisation du coût du gaz et des performances

0

L’un des aspects les plus importants lors de l’écriture de contrats intelligents est l’optimisation du coût du gaz et des performances. Dans ce tutoriel, je vais vous expliquer les meilleures pratiques pour optimiser le coût du gaz et les performances de vos contrats intelligents Solidity.

  1. Évitez les boucles inutiles

L’utilisation de boucles peut parfois être nécessaire pour effectuer des opérations répétitives, mais elles peuvent être très coûteuses en termes de gaz. Par conséquent, il est important de limiter le nombre de boucles dans votre code et de les rendre aussi efficaces que possible.

Voici un exemple de code qui utilise une boucle « for » pour parcourir un tableau :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    uint[] public myArray;

    function addToArray(uint _value) public {
        myArray.push(_value);
    }

    function sumArray() public view returns (uint) {
        uint sum = 0;
        for (uint i = 0; i < myArray.length; i++) {
            sum += myArray[i];
        }
        return sum;
    }
}

Dans cet exemple, la fonction « sumArray » parcourt le tableau « myArray » pour calculer la somme de tous ses éléments. Cependant, chaque itération de la boucle coûte du gaz, ce qui peut être coûteux si le tableau est très grand.

Une façon d’optimiser ce code est d’utiliser une variable « total » pour stocker la somme à mesure que vous parcourez le tableau. Cela vous permet de vous passer de la boucle « for » et donc de réduire considérablement les coûts de gaz.

Voici le code mis à jour avec cette optimisation :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    uint[] public myArray;

    function addToArray(uint _value) public {
        myArray.push(_value);
    }

    function sumArray() public view returns (uint) {
        uint total = 0;
        for (uint i = 0; i < myArray.length; i++) {
            total += myArray[i];
        }
        return total;
    }
}
  1. Évitez les appels de fonction coûteux

Les appels de fonction sont également coûteux en termes de gaz, car ils nécessitent une interaction avec la blockchain. Par conséquent, il est important de limiter le nombre d’appels de fonction dans votre code et de les rendre aussi efficaces que possible.

Voici un exemple de code qui récupère une valeur à partir d’un autre contrat à chaque appel :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    function getValueFromOtherContract(address _otherContract) public view returns (uint) {
        return OtherContract(_otherContract).getValue();
    }
}

contract OtherContract {
    uint public value;

    function setValue(uint _value) public {
        value = _value;
    }

    function getValue() public view returns (uint) {
        return value;
    }
}

Dans cet exemple, la fonction « getValueFromOtherContract » récupère la valeur « value » du contrat « OtherContract ». Cependant, à chaque appel de cette fonction, une interaction avec le contrat « OtherContract » est nécessaire, ce qui peut coûter cher en termes de gaz.

Une façon d’optimiser ce code est de stocker la valeur « value » dans le contrat « MyContract » chaque fois qu’elle est modifiée dans le contrat « OtherContract ». Cela vous permet de vous passer de l’appel de fonction coûteux dans la fonction « getValueFromOther »

Voici le code mis à jour avec cette optimisation :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    uint public value;

    function setValueFromOtherContract(uint _value) public {
        value = _value;
    }
}

contract OtherContract {
    uint public value;
    MyContract public myContract;

    constructor(address _myContract) {
        myContract = MyContract(_myContract);
    }

    function setValue(uint _value) public {
        value = _value;
        myContract.setValueFromOtherContract(value);
    }
}

Dans cet exemple, nous avons ajouté une fonction « setValueFromOtherContract » dans le contrat « MyContract » qui stocke la valeur « value » chaque fois qu’elle est modifiée dans le contrat « OtherContract ». Nous avons également ajouté une référence au contrat « MyContract » dans le contrat « OtherContract » afin de pouvoir appeler cette fonction.

  1. Utilisez les types de données appropriés

L’utilisation des types de données appropriés peut également aider à optimiser le coût du gaz et les performances de votre contrat. Par conséquent, il est important de choisir les types de données les plus appropriés pour vos variables.

Voici un exemple de code qui utilise un entier signé (int) pour stocker une valeur qui ne peut jamais être négative :

arduinoCopy codepragma solidity ^0.8.0;

contract MyContract {
    int public value;

    function setValue(int _value) public {
        value = _value;
    }
}

Dans cet exemple, la variable « value » ne peut jamais être négative, mais nous avons utilisé un entier signé (int) pour la stocker. Cela peut entraîner des problèmes de sécurité potentiels et peut également augmenter les coûts de gaz, car les opérations de calcul sur les entiers signés sont plus complexes que sur les entiers non signés (uint).

Une façon d’optimiser ce code est d’utiliser un entier non signé (uint) à la place. Cela garantit que la variable ne peut jamais être négative et réduit également les coûts de gaz.

Voici le code mis à jour avec cette optimisation :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    uint public value;

    function setValue(uint _value) public {
        value = _value;
    }
}

  1. Évitez les opérations de virgule flottante

Les opérations de virgule flottante (float) sont très coûteuses en termes de gaz et peuvent affecter les performances de votre contrat. Par conséquent, il est important d’éviter autant que possible les opérations de virgule flottante dans votre code.

Voici un exemple de code qui utilise une opération de virgule flottante pour calculer une division :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    function divide(uint _numerator, uint _denominator) public pure returns (uint) {
        return _numerator / _denominator;
    }
}

Dans cet exemple, la fonction « divide » utilise l’opération de division pour calculer le résultat. Cependant, cette opération peut être très coûteuse en termes de gaz, en particulier si les nombres sont grands.

Une façon d’optimiser ce code est d’utiliser des opérations d’entiers (int) à la place. Si vous avez besoin d’une division, vous pouvez utiliser une multiplication inversée pour obtenir

un résultat similaire. Cela réduit considérablement les coûts de gaz.

Voici le code mis à jour avec cette optimisation :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    function divide(uint _numerator, uint _denominator) public pure returns (uint) {
        uint result = _numerator * 100 / _denominator;
        return result;
    }
}

Dans cet exemple, nous avons utilisé une multiplication inversée pour obtenir le résultat de la division. Nous avons multiplié le numérateur par 100 et avons ensuite divisé par le dénominateur. Cela nous donne un résultat similaire à la division, mais avec des opérations d’entiers moins coûteuses en termes de gaz.

5. Évitez les fonctions récursives

Les fonctions récursives peuvent être très coûteuses en termes de gaz et peuvent entraîner des dépassements de pile. Par conséquent, il est important d’éviter autant que possible les fonctions récursives dans votre code.

Voici un exemple de code qui utilise une fonction récursive pour calculer un nombre factoriel :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    function factorial(uint _num) public pure returns (uint) {
        if (_num == 0) {
            return 1;
        } else {
            return _num * factorial(_num - 1);
        }
    }
}

Dans cet exemple, la fonction « factorial » utilise une fonction récursive pour calculer le nombre factoriel d’un nombre donné. Cependant, cela peut être très coûteux en termes de gaz, surtout si le nombre est grand.

Une façon d’optimiser ce code est d’utiliser une boucle « for » à la place. Cela réduit considérablement les coûts de gaz.

Voici le code mis à jour avec cette optimisation :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    function factorial(uint _num) public pure returns (uint) {
        uint result = 1;
        for (uint i = 2; i <= _num; i++) {
            result *= i;
        }
        return result;
    }
}

Dans cet exemple, nous avons utilisé une boucle « for » pour calculer le nombre factoriel d’un nombre donné. Nous initialisons la variable « result » à 1 et parcourons ensuite tous les nombres de

2 à « _num », en multipliant « result » par chaque nombre. Cela nous donne le nombre factoriel du nombre donné, mais avec une complexité algorithmique et des coûts de gaz considérablement réduits.

6. Utilisez des structures de données appropriées

Le choix de la bonne structure de données peut également aider à optimiser le coût du gaz et les performances de votre contrat. Par conséquent, il est important de choisir la structure de données la plus appropriée pour votre cas d’utilisation spécifique.

Voici un exemple de code qui utilise un tableau pour stocker des données avec des clés :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    struct MyData {
        uint id;
        uint value;
    }

    MyData[] public myDataArray;

    function addData(uint _id, uint _value) public {
        myDataArray.push(MyData(_id, _value));
    }

    function getData(uint _id) public view returns (uint) {
        for (uint i = 0; i < myDataArray.length; i++) {
            if (myDataArray[i].id == _id) {
                return myDataArray[i].value;
            }
        }
        revert("Data not found.");
    }
}

Dans cet exemple, nous utilisons un tableau pour stocker des données avec des clés. Nous utilisons ensuite une boucle « for » pour rechercher la valeur correspondant à une clé donnée.

Cependant, cette approche peut être très coûteuse en termes de gaz, en particulier si le tableau est très grand. Une façon d’optimiser ce code est d’utiliser une carte (mapping) à la place. Les cartes sont des structures de données qui permettent de stocker des valeurs en fonction de clés, ce qui les rend plus efficaces pour la recherche de données.

Voici le code mis à jour avec cette optimisation :

csharpCopy codepragma solidity ^0.8.0;

contract MyContract {
    mapping (uint => uint) public myDataMap;

    function addData(uint _id, uint _value) public {
        myDataMap[_id] = _value;
    }

    function getData(uint _id) public view returns (uint) {
        return myDataMap[_id];
    }
}

Dans cet exemple, nous avons utilisé une carte « myDataMap » pour stocker les données avec des clés. Nous utilisons ensuite cette carte pour récupérer la valeur correspondant à une clé donnée. Cette approche est beaucoup plus efficace en termes de gaz et de performances que la boucle « for » utilisée dans l’exemple précédent.

Conclusion

L’optimisation du coût du gaz et des performances est un aspect important de la programmation des contrats intelligents Solidity. En suivant les meilleures pratiques décrites dans ce tutoriel, vous pouvez réduire considérablement les coûts de gaz et améliorer les performances de vos contrats. Cependant, il est important de tester soigneusement votre code pour vous assurer que toutes les fonctionnalités sont préservées avant de le déployer 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.