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