Solidity Analyzers
Static code analysis is a process of debugging code by examining it without executing it.
The Solidity Analyzers plugin combines three analysis tools to perform static analysis on Solidity smart contracts. Each tool checks for security vulnerabilities and bad development practices, among other issues. The plugin can be activated from the Remix Plugin Manager.

Solidity Analyzers can also be loaded by clicking on the Solidity icon in the featured plugins section of Remix’s home tab. This button loads the following plugins: Solidity Compiler, Solidity Unit Testing, and Static Analyzers.
Solidity Analyzers uses these tools:
Remix Analysis: a basic analysis tool
Solhint linter: a Solidity linter for code and style guide validations
Slither Static Analysis: a comprehensive static analysis tool
Note
Slither can only be used on Remix Desktop.
Comment l’utiliser ?
A contract must be compiled before analysis can be run.
At the top of the panel, check the tools that you want to use.

Errors & Warnings
By default, Solidity Analyzers will show both errors and warnings. The combined number of errors and warnings is shown in the badge on that tool’s tab.

If you check Hide warnings, warnings will be hidden and you’ll exclusively see the errors.
NOTE: Remix Analysis does not flag errors — it only shows warnings, so if you check Hide warnings, nothing will be shown in the Remix Analysis tab.

Warnings from external libraries
By default, warnings from external libraries are not shown. If you check the box Show warnings for external libraries, the tools will also analyze the external libraries for warnings.
Slither
To run Slither with this plugin, you need to open your workspace on Remix Desktop.
Solhint
The Solhint linter can be run without connecting Remix to your filesystem.
Remix analysis
Remix Analysis has 4 categories: Security, Gas & Economy, ERC & Miscellaneous.
Here is the list of modules under each category along with example code which should be avoided or used very carefully during development:
Catégorie : Sécurité
Origine de la transaction : “tx.origin” est utilisé
tx.origin n’est utile que dans des cas très exceptionnels. Si vous l’utilisez pour l’authentification, vous voulez généralement le remplacer par « msg.sender », parce que sinon n’importe quel contrat que vous appelez peut agir en votre nom.
Exemple:________________.
require(tx.origin == owner);
Vérifiez les effets : Bogues potentiels de réentrance
La violation potentielle du modèle Checks-Effects-Interaction peut entraîner une vulnérabilité de réentrance.
Exemple:________________.
// sending ether first
msg.sender.transfer(amount);
// updating state afterwards
balances[msg.sender] -= amount;
Assemblage en ligne : Assemblage en ligne utilisé
L’utilisation de l’assemblage en ligne n’est conseillée que dans de rares cas.
Exemple:________________.
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(_addr)
}
Block timestamp: Semantics may be unclear
now ne signifie pas l’heure actuelle. now est un alias de block.timestamp. block.timestamp peut être influencé par les mineurs dans une certaine mesure, soyez prudent.
Exemple:________________.
// using now for date comparison
if(startDate > now)
isStarted = true;
// using block.timestamp
uint c = block.timestamp;
Low level calls: Semantics may be unclear
L’utilisation de call, callcode ou delegatecall de bas niveau doit être évitée autant que possible. send ne lève pas d’exception en cas d’échec, assurez-vous de traiter le cas d’échec en conséquence. Utilisez transfer lorsque l’échec du transfert d’éther doit annuler toute la transaction.
Exemple:________________.
x.call('something');
x.send(1 wei);
Blockhash usage: Semantics may be unclear
blockhash est utilisé pour accéder aux 256 derniers hashs de blocs. Un mineur calcule le hachage du bloc en « résumant » les informations contenues dans le bloc en cours de minage. En résumant les informations de manière intelligente, un mineur peut essayer d’influencer le résultat d’une transaction dans le bloc en cours.
Exemple:________________.
bytes32 b = blockhash(100);
L’autodestruction : Méfiez-vous des contrats d’appel
selfdestruct peut bloquer les contrats appelants de manière inattendue. Soyez particulièrement prudent si ce contrat est prévu pour être utilisé par d’autres contrats (par exemple, des contrats de bibliothèque, des interactions). L’autodestruction du contrat de l’appelant peut laisser les appelants dans un état inopérant.
Exemple:________________.
selfdestruct(address(0x123abc..));
Catégorie : Gaz et économie
Coûts du gaz : Besoins en gaz trop élevés pour les fonctions
If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage.
Exemple:________________.
for (uint8 proposal = 0; proposal < proposals.length; proposal++) {
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount;
winningProposal = proposal;
}
}
Ceci sur les appels locaux : Invocation de fonctions locales via “this”.
N’utilisez jamais this pour appeler des fonctions dans le même contrat, cela ne fait que consommer plus de gaz que les appels locaux normaux.
Exemple:________________.
contract test {
function callb() public {
address x;
this.b(x);
}
function b(address a) public returns (bool) {}
}
Suppression d’un tableau dynamique : Utilisez require/assert de manière appropriée
L’opération delete lorsqu’elle est appliquée à un tableau de taille dynamique dans Solidity génère du code pour supprimer chacun des éléments contenus. Si le tableau est grand, cette opération peut dépasser la limite de gaz du bloc et soulever une exception OOG. Des objets imbriqués de taille dynamique peuvent également produire les mêmes résultats.
Exemple:________________.
contract arr {
uint[] users;
function resetState() public{
delete users;
}
}
Boucle de forçage sur un tableau dynamique : Les itérations dépendent de la taille du tableau dynamique
Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully: Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can stall the complete contract at a certain point. Additionally, using unbounded loops can incur a lot of avoidable gas costs. Carefully test how many items at maximum you can pass to such functions to make it successful.
Exemple:________________.
contract forLoopArr {
uint[] array;
function shiftArrItem(uint index) public returns(uint[] memory) {
for (uint i = index; i < array.length; i++) {
array[i] = array[i+1];
}
return array;
}
}
Transfert d’Ether dans une boucle : Transfert d’Ether dans une boucle for/while/do-while.
Ether payout should not be done in a loop. Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. If required, make sure that the number of iterations is low and you trust each address involved.
Exemple:________________.
contract etherTransferInLoop {
address payable owner;
function transferInForLoop(uint index) public {
for (uint i = index; i < 100; i++) {
owner.transfer(i);
}
}
function transferInWhileLoop(uint index) public {
uint i = index;
while (i < 100) {
owner.transfer(i);
i++;
}
}
}
Catégorie : ERC
ERC20 : « decimals » doit être remplacé par « uint8 ».
ERC20 contracts” decimals function should have uint8 as the return type.
Exemple:________________.
contract EIP20 {
uint public decimals = 12;
}
Catégorie : Divers
Fonctions constantes/vues/pures : Fonctions potentiellement constantes/vues/pures
Il met en garde contre les méthodes qui devraient potentiellement être constantes/visibles/pures mais qui ne le sont pas.
Exemple:________________.
function b(address a) public returns (bool) {
return true;
}
Noms de variables similaires : Les noms de variables sont trop similaires
Il met en garde contre l’utilisation de noms de variables similaires.
Exemple:________________.
// Variables have very similar names voter and voters.
function giveRightToVote(address voter) public {
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
Pas de retour : La fonction avec des « retours » ne renvoie pas d’information
Il met en garde contre les méthodes qui définissent un type de retour mais ne renvoient jamais explicitement une valeur.
Exemple:________________.
function noreturn(string memory _dna) public returns (bool) {
dna = _dna;
}
Respectez les conditions : Utilisez les termes « exiger » et « affirmer » de manière appropriée.
Utilisez assert(x) si vous ne voulez jamais que x soit faux, en aucune circonstance (à part un bug dans votre code). Utilisez require(x) si x peut être faux, à cause par exemple d’une entrée invalide ou d’un composant externe défaillant.
Exemple:________________.
assert(a.balance == 0);
Résultat non utilisé : Le résultat d’une opération non utilisée
Une opération binaire produit une valeur qui n’est pas utilisée dans la suite. Cela est souvent dû à une confusion entre l’affectation (=) et la comparaison (==).
Exemple:________________.
c == 5;
or
a + b;
Longueur de la chaîne : Longueur des octets != Longueur de la chaîne
Les octets et la longueur de la chaîne ne sont pas les mêmes puisque les chaînes sont supposées être encodées en UTF-8 (selon la définition de l’ABI) et qu’un caractère n’est donc pas nécessairement encodé dans un octet de données.
Exemple:________________.
function length(string memory a) public pure returns(uint) {
bytes memory x = bytes(a);
return x.length;
}
Suppression d’un tableau dynamique : “delete” sur un tableau laisse un vide
L’utilisation de delete sur un tableau laisse un vide. La longueur du tableau reste la même. Si vous souhaitez supprimer la position vide, vous devez décaler les éléments manuellement et mettre à jour la propriété length.
Exemple:________________.
contract arr {
uint[] array = [1,2,3];
function removeAtIndex() public returns (uint[] memory) {
delete array[1];
return array;
}
}
Données tronquées : La division sur des valeurs int/uint tronque le résultat
La division de valeurs entières donne à nouveau une valeur entière. Cela signifie que, par exemple, 10 / 100 = 0 au lieu de 0,1 puisque le résultat est à nouveau un nombre entier. Ce n’est pas le cas pour la division de valeurs littérales (uniquement), qui donnent des constantes rationnelles.
Exemple:________________.
function contribute() payable public {
uint fee = msg.value * uint256(feePercentage / 100);
fee = msg.value * (p2 / 100);
}
Analyseur de remix
remix-analyzer is the library which works underneath the Remix Analysis tool.
remix-analyzer is an NPM package. It can be used as a library in a solution supporting Node.js. Find more information about this type of usage in the remix-analyzer repository.