assert() evalúa una condición booleana y detiene la ejecución si esta es false. A diferencia de require(), que está diseñado para validar entradas o restricciones del usuario, assert() se utiliza exclusivamente para verificar invariantes del contrato, es decir, propiedades internas que deben mantenerse válidas en todo momento.
assert(condición);
true durante la ejecución del contrato.
1. Errores críticos: Se usa para identificar errores que indican fallos lógicos graves en el contrato.
2. Sin mensaje de error: A diferencia de require(), no permite mensajes personalizados.
3. Uso de gas: Consume todo el gas disponible si la condición es false.
assert() y require()
| Característica |
assert()
|
require()
|
|---|---|---|
| Uso principal | Validar invariantes y errores internos. | Validar entradas y restricciones. |
| Mensaje de error | No admite mensajes personalizados. | Permite incluir un mensaje. |
| Comportamiento al fallar | Consume todo el gas y revierte cambios. | Reembolsa el gas no utilizado. |
assert()
pragma solidity ^0.8.0;
contract Invariantes {
uint public total;
// Incrementar el total
function incrementar(uint _cantidad) public {
total += _cantidad;
// Verificar que el total nunca sea negativo
assert(total >= _cantidad);
}
}
En este ejemplo, assert() asegura que la variable total nunca sea negativa, lo cual sería un error lógico en el contrato.
contract Estados {
enum Estado { Inactivo, Activo }
Estado public estado;
constructor() {
estado = Estado.Inactivo;
}
function activar() public {
estado = Estado.Activo;
}
function verificarEstado() public view {
// Asegurarse de que el estado siempre sea válido
assert(estado == Estado.Inactivo || estado == Estado.Activo);
}
}
Aquí, assert() verifica que el estado siempre sea válido dentro del conjunto de valores permitidos por la enumeración Estado.
contract Balances {
mapping(address => uint) public balances;
function transferir(address _destinatario, uint _cantidad) public {
balances[msg.sender] -= _cantidad;
balances[_destinatario] += _cantidad;
// Comprobación de que el balance total sea coherente
assert(balances[msg.sender] + balances[_destinatario] >= _cantidad);
}
}
En este caso, assert() verifica que los balances sean consistentes después de una transferencia.
contract Limites {
uint8 public contador;
function incrementar() public {
contador++;
// Asegurar que no haya un desbordamiento
assert(contador > 0);
}
}
Antes de Solidity 0.8, assert() era utilizado frecuentemente para detectar desbordamientos aritméticos. A partir de esta versión, Solidity incluye comprobaciones automáticas de desbordamiento, pero assert() sigue siendo útil para verificar otras propiedades críticas.
assert()
1. Uso exclusivo para invariantes: Limita el uso de assert() a comprobaciones internas que siempre deben cumplirse, independientemente de la entrada del usuario.
2. Evita abusos: No uses assert() para validaciones regulares; para ello, utiliza require().
3. Testeo exhaustivo: Asegúrate de probar el contrato a fondo para detectar posibles fallos en las condiciones verificadas por assert().
assert()
1. Reversión completa: Detiene la ejecución y revierte todos los cambios realizados en la transacción.
2. Consumo de gas: Todo el gas proporcionado para la transacción se consume, lo que puede hacer costosa una falla de assert().
3. Indicativo de errores críticos: Una falla en assert() indica que hay un fallo lógico en el contrato que debe ser corregido.
assert() únicamente para verificar invariantes y propiedades internas.
assert() con testeo automatizado para garantizar la estabilidad.
assert() en situaciones ya protegidas, como desbordamientos aritméticos.
Para más información sobre assert(), consulta la documentación oficial de Solidity.
Jorge García
Fullstack developer