Analizadores de solidez
El análisis estático del código es un proceso de depuración del código examinándolo sin ejecutarlo.
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 utiliza estas herramientas:
Análisis de remezclas: una herramienta básica de análisis
Solhint linter: un linter de Solidity para validaciones de código y guías de estilo
Slither Static Analysis: a comprehensive static analysis tool
Nota
Slither can only be used on Remix Desktop.
Cómo utilizarlo
Un contrato debe compilarse antes de poder ejecutar el análisis.
En la parte superior del panel, marque las herramientas que desee utilizar.

Errores y advertencias
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.

Si marca Ocultar advertencias, las advertencias se ocultarán y verá exclusivamente los errores.
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.

Avisos de bibliotecas externas
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
El linter Solhint puede ejecutarse sin conectar Remix a su sistema de archivos.
Remix analysis
Remix Analysis tiene 4 categorías: Seguridad, Gas y Economía, ERC y Varios.
Here is the list of modules under each category along with example code which should be avoided or used very carefully during development:
Categoría: Seguridad
Origen de la transacción: se utiliza “tx.origin”
tx.origin sólo es útil en casos muy excepcionales. Si lo utiliza para la autenticación, normalmente querrá sustituirlo por msg.sender, porque de lo contrario cualquier contrato al que llame podrá actuar en su nombre.
Ejemplo:
require(tx.origin == owner);
Comprobar efectos: Posibles fallos de reentrada
La violación potencial del patrón Comprobaciones-Efectos-Interacción puede conducir a una vulnerabilidad de reentrada.
Ejemplo:
// sending ether first
msg.sender.transfer(amount);
// updating state afterwards
balances[msg.sender] -= amount;
Montaje en línea: Montaje en línea utilizado
Se aconseja utilizar el montaje en línea sólo en casos excepcionales.
Ejemplo:
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(_addr)
}
Block timestamp: Semantics may be unclear
now no significa hora actual. now es un alias de block.timestamp. block.timestamp puede estar influenciado por los mineros hasta cierto punto, tenga cuidado.
Ejemplo:
// using now for date comparison
if(startDate > now)
isStarted = true;
// using block.timestamp
uint c = block.timestamp;
Low level calls: Semantics may be unclear
El uso de call, callcode o delegatecall de bajo nivel debe evitarse siempre que sea posible. send no lanza una excepción cuando no tiene éxito, asegúrese de tratar el caso de fallo como corresponda. Utilice transfer siempre que el fallo de la transferencia de éter deba hacer retroceder toda la transacción.
Ejemplo:
x.call('something');
x.send(1 wei);
Blockhash usage: Semantics may be unclear
blockhash se utiliza para acceder a los últimos 256 hashes de bloque. Un minero calcula el hash del bloque «sumando» la información del bloque actual minado. Al sumar la información de forma inteligente, un minero puede intentar influir en el resultado de una transacción en el bloque actual.
Ejemplo:
bytes32 b = blockhash(100);
Autodestrucción: Cuidado con los contratos de llamadas
selfdestruct puede bloquear contratos de llamada inesperadamente. Tenga especial cuidado si está previsto que este contrato sea utilizado por otros contratos (por ejemplo, contratos de biblioteca, interacciones). La autodestrucción del contrato llamante puede dejar a los contratos llamantes en un estado inoperativo.
Ejemplo:
selfdestruct(address(0x123abc..));
Categoría: Gas y economía
Costes de gas: Demasiado alto requerimiento de gas de las funciones
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.
Ejemplo:
for (uint8 proposal = 0; proposal < proposals.length; proposal++) {
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount;
winningProposal = proposal;
}
}
This en llamadas locales: Invocación de funciones locales a través de “this”
Nunca utilice this para llamar a funciones en el mismo contrato, sólo consume más gas que las llamadas locales normales.
Ejemplo:
contract test {
function callb() public {
address x;
this.b(x);
}
function b(address a) public returns (bool) {}
}
Borrar en array dinámico: Utilice require/assert adecuadamente
La operación delete cuando se aplica a un array de tamaño dinámico en Solidity genera código para borrar cada uno de los elementos que contiene. Si el array es grande, esta operación puede sobrepasar el límite de gas del bloque y lanzar una excepción OOG. También los objetos anidados de tamaño dinámico pueden producir los mismos resultados.
Ejemplo:
contract arr {
uint[] users;
function resetState() public{
delete users;
}
}
Bucle for sobre matriz dinámica: Las iteraciones dependen del tamaño del array dinámico
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.
Ejemplo:
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;
}
}
Transferencia de éter en un bucle: Transferencia de éter en un bucle 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.
Ejemplo:
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++;
}
}
}
Categoría: ERC
ERC20: “decimales” debería ser “uint8”
ERC20 contracts” decimals function should have uint8 as the return type.
Ejemplo:
contract EIP20 {
uint public decimals = 12;
}
Categoría: Varios
Funciones constantes/vistas/puras: Funciones potencialmente constantes/vistas/puras
Advierte de los métodos que potencialmente deberían ser constantes/vistos/puros pero no lo son.
Ejemplo:
function b(address a) public returns (bool) {
return true;
}
Nombres de variables similares: Los nombres de las variables son demasiado similares
Advierte sobre el uso de nombres de variables similares.
Ejemplo:
// Variables have very similar names voter and voters.
function giveRightToVote(address voter) public {
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
Sin retorno: Función con “returns” no retorna
Advierte de los métodos que definen un tipo de retorno pero nunca devuelven explícitamente un valor.
Ejemplo:
function noreturn(string memory _dna) public returns (bool) {
dna = _dna;
}
Guarde las condiciones: Utilice “require” y “assert” adecuadamente
Utilice assert(x) si nunca jamás quiere que x sea falso, en ninguna circunstancia (aparte de un error en su código). Utilice require(x) si x puede ser falso, debido, por ejemplo, a una entrada no válida o a un componente externo que falle.
Ejemplo:
assert(a.balance == 0);
Resultado no utilizado: El resultado de una operación no utilizada
Una operación binaria produce un valor que no se utiliza en la siguiente. Esto suele deberse a la confusión entre asignación (=) y comparación (==).
Ejemplo:
c == 5;
or
a + b;
Longitud de la cadena: Longitud de bytes != Longitud de cadena
Los bytes y la longitud de la cadena no son lo mismo, ya que se supone que las cadenas están codificadas en UTF-8 (según la definición de la ABI), por lo que un carácter no está necesariamente codificado en un byte de datos.
Ejemplo:
function length(string memory a) public pure returns(uint) {
bytes memory x = bytes(a);
return x.length;
}
Borrar de un array dinámico: “borrar” en un array deja un hueco
Utilizar delete en un array deja un hueco. La longitud del array sigue siendo la misma. Si desea eliminar la posición vacía, deberá desplazar los elementos manualmente y actualizar la propiedad de longitud.
Ejemplo:
contract arr {
uint[] array = [1,2,3];
function removeAtIndex() public returns (uint[] memory) {
delete array[1];
return array;
}
}
Datos truncados: La división en valores int/uint trunca el resultado
La división de valores enteros vuelve a dar como resultado un valor entero. Esto significa, por ejemplo, que 10 / 100 = 0 en lugar de 0,1, ya que el resultado vuelve a ser un número entero. Esto no es válido para la división de (sólo) valores literales ya que esos dan constantes racionales.
Ejemplo:
function contribute() payable public {
uint fee = msg.value * uint256(feePercentage / 100);
fee = msg.value * (p2 / 100);
}
Analizador de remezclas
remix-analyzer es la biblioteca que funciona por debajo de la herramienta Remix Analysis.
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.