BudiBadu Logo
Samplebadu

Solidity by Example: Error Handling

0.8.x

Robust error handling with this code example demonstrating custom error definitions for gas efficiency, the revert statement with error parameters, require for input validation, assert for invariant checking, and transaction rollback behavior.

Code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ErrorExample {
    // Custom error (gas efficient)
    error InsufficientBalance(uint256 available, uint256 required);

    mapping(address => uint256) balances;

    function withdraw(uint256 _amount) public {
        uint256 bal = balances[msg.sender];

        // Old way: require with string
        // require(bal >= _amount, "Insufficient balance");

        // New way: Custom Error
        if (bal < _amount) {
            revert InsufficientBalance(bal, _amount);
        }

        balances[msg.sender] -= _amount;
    }

    function testAssert() public view {
        // Assert is for internal invariants (should never be false)
        // If this fails, there is a bug in the contract
        assert(balances[msg.sender] >= 0); 
    }
}

Explanation

Error handling in Solidity uses require, revert, and assert to validate conditions and handle failures. When an error occurs, the transaction reverts completely, undoing all state changes and returning remaining gas to the caller. The require statement is used for input validation and conditions that users might violate, such as insufficient balance or invalid parameters. The assert statement checks internal invariants that should never be false, if an assert fails, it indicates a bug in the contract logic.

Solidity 0.8.4 introduced custom errors defined with the error keyword, offering significant gas savings compared to require with string messages. String error messages are stored on-chain and consume substantial gas, while custom errors only store a 4-byte selector. Custom errors can also include parameters, allowing you to pass detailed information back to the caller about why the transaction failed, such as showing both the available and required amounts.

The revert statement is used with custom errors or when you need conditional logic before reverting. It provides more flexibility than require for complex validation scenarios. All three error handling mechanisms cause the transaction to fail and revert state changes, but they differ in gas refunds and intended use cases. Understanding when to use each is crucial for writing secure, gas-efficient smart contracts.

Code Breakdown

6
error InsufficientBalance(...) defines a gas-efficient custom error type.
18
revert InsufficientBalance(...) aborts execution with error data.
14
require with string messages costs more gas than custom errors.
27
assert checks invariants that should never fail, indicating bugs if they do.