El bloque try/catch permite manejar errores de manera estructurada al realizar llamadas externas a otros contratos o al ejecutar funciones con operaciones que podrían fallar.
1. Manejo de errores externos:
2. Resiliencia:
3. Eficiencia:
try/catch
try objetoContrato.funcion(args) returns (tipoRetorno) {
// Código a ejecutar si la llamada es exitosa
} catch {
// Código a ejecutar si ocurre un error
}
1. Errores generales:
catch {
// Manejo genérico de errores
}
2. Errores específicos (Error):
catch Error(string memory razon) {
// Manejo de errores con mensaje de revert
}
3. Errores bajos (Panic):
catch Panic(uint256 codigoError) {
// Manejo de errores críticos
}
contract ContratoExterno {
function dividir(uint a, uint b) public pure returns (uint) {
require(b != 0, "Division por cero");
return a / b;
}
}
pragma solidity ^0.8.0;
contract ManejoErrores {
ContratoExterno public contratoExterno;
constructor(address _direccionContratoExterno) {
contratoExterno = ContratoExterno(_direccionContratoExterno);
}
function dividirNumeros(uint a, uint b) public view returns (string memory) {
try contratoExterno.dividir(a, b) returns (uint resultado) {
return string(abi.encodePacked("Resultado: ", uint2str(resultado)));
} catch Error(string memory razon) {
return string(abi.encodePacked("Error: ", razon));
} catch {
return "Error desconocido";
}
}
function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len - 1;
while (_i != 0) {
bstr[k--] = bytes1(uint8(48 + _i % 10));
_i /= 10;
}
return string(bstr);
}
}
En este ejemplo:
"Division por cero"
.
catch
general.
try/catch
1. Error:
require
o revert
con un mensaje de error.
catch Error(string memory razon) {
// Manejo basado en la razón del error
}
2. Panic:
catch Panic(uint codigoError) {
// Manejo basado en el código del error
}
3. Errores de bajo nivel:
catch {
// Manejo genérico
}
contract Receptor {
function recibirEther() public payable {
require(msg.value >= 1 ether, "Debe enviar al menos 1 Ether");
}
}
contract ManejoTransferencias {
Receptor public receptor;
constructor(address _direccionReceptor) {
receptor = Receptor(_direccionReceptor);
}
function enviarEther() public payable returns (string memory) {
try receptor.recibirEther{value: msg.value}() {
return "Transferencia exitosa";
} catch Error(string memory razon) {
return string(abi.encodePacked("Error: ", razon));
} catch {
return "Error desconocido en la transferencia";
}
}
}
En este ejemplo:
catch
genérico.
try/catch
1. Usar mensajes claros:
2. Evitar abusos:
try/catch
para manejar errores internos del mismo contrato; está diseñado principalmente para interacciones externas.
3. Optimización de gas:
try/catch
solo a interacciones críticas para evitar un sobrecosto innecesario en gas.
4. Documentación:
try/catch
1. Solo para llamadas externas:
try/catch
para manejar errores dentro del mismo contrato.
2. Mayor consumo de gas:
3. Compatibilidad:
try/catch
1. Mayor control sobre fallos externos:
2. Resiliencia:
3. Depuración avanzada:
Para más detalles sobre try/catch
, consulta la documentación oficial de Solidity.
Jorge García
Fullstack developer