In Solidity, exception handling is an essential mechanism for ensuring the security and stability of smart contracts. When an exception occurs, the current transaction is reverted (rolled back), and the state of the blockchain remains unchanged. Solidity provides several built-in keywords and techniques to handle errors effectively.
Here are the main tools available:
1. require
The require statement is used to validate input parameters or contract state conditions. If the condition is not met, the transaction is reverted, an error message is returned, and unused gas is refunded.
Example:
function transfer(address to, uint256 amount) public {
require(amount <= balances[msg.sender], "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
}
Here, require ensures the sender has enough balance before transferring. If not, the transaction fails with the error message "Insufficient balance".
2. assert
The assert keyword is used to detect programming errors or inconsistent internal states. Unlike require, when an assert fails, all gas is consumed (not refunded), because it usually signals a serious bug.
Example:
function transfer(address to, uint256 amount) public {
assert(amount > 0); // should never fail in correct logic
balances[msg.sender] -= amount;
balances[to] += amount;
}
Here, assert guarantees that the transfer amount is always greater than zero. If it fails, it indicates a bug in the code, not a user error.
3. revert
The revert statement can be used to explicitly trigger an error. It works similarly to require but provides more flexibility, especially for complex conditions or external contract calls.
Example:
function withdraw(uint256 amount) public {
if (balances[msg.sender] < amount) {
revert("Insufficient balance");
}
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
Here, revert is used to handle insufficient balance with a clear error message.
4. Custom Errors (Introduced in Solidity 0.8.0)
Custom errors are a gas-efficient way to handle exceptions. Instead of using long error strings, developers can define structured error types using the error keyword.
Example:
// Define a custom error
error InsufficientBalance(uint256 balance, uint256 withdrawalAmount);
function withdraw(uint256 amount) public {
if (balances[msg.sender] < amount) {
revert InsufficientBalance({
balance: balances[msg.sender],
withdrawalAmount: amount
});
}
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
Here, a custom error InsufficientBalance provides structured information (the user’s balance and attempted withdrawal) while saving gas compared to string-based error messages.
Summary
require→ For checking user inputs and contract state. Refunds unused gas on failure.assert→ For catching bugs and impossible conditions. Consumes all gas if it fails.revert→ For explicit error handling with flexible conditions.- Custom Errors → Gas-efficient, structured error reporting (introduced in Solidity 0.8+).
By using these exception-handling mechanisms properly, developers can build secure, reliable, and efficient smart contracts that protect users and maintain blockchain integrity.



