Examples on Error Handling in Solidity
Tags: solidity, ethereum, web3, blockchain
Published: 2023-03-07 17:21:30

>Solidity uses state-reverting exceptions to handle errors and provides three error handling functions: assert, require, and revert

Error handling in Solidity is important to ensure that the contracts behave as expected and do not result in unexpected behavior or loss of funds. Solidity provides several error-handling mechanisms such as assert, require, and revert. The assert function checks for conditions that should never occur and throws an exception if they do. The require function checks for conditions that must be met before executing the contract and throws an exception if they are not met. The revert function is similar to require but it allows for a custom error message to be returned when the condition fails. Solidity also provides try/catch statements which were introduced in version 0.6.0, allowing developers to catch exceptions thrown by external function calls or contract creations. It's important to note that runtime errors are difficult to catch and can occur while executing contracts, such as out-of-gas errors, data type overflow errors, divide by zero errors, array-out-of-index errors, etc. Therefore, it's crucial to handle these errors properly using the available mechanisms provided by Solidity.
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Error {
    function testRequire(uint i) public pure {
        // Require should be used to validate conditions such as:
        // - inputs
        // - conditions before execution
        // - return values from calls to other functions
        require(i > 10, "Input must be greater than 10");
    }

    function testRevert(uint i) public pure {
        // Revert is useful when the condition to check is complex.
        // This code does the exact same thing as the example above
        if (i <= 10) {
            revert("Input must be greater than 10");
        }
    }

    uint public num;

    function testAssert() public view {
        // Assert should only be used to test for internal errors,
        // and to check invariants.

        // Here we assert that num is always equal to 0
        // since it is impossible to update the value of num
        assert(num == 0);
    }

    // custom error
    error InsufficientBalance(uint balance, uint withdrawAmount);

    function testCustomError(uint withdrawAmount) public view {
        uint bal = address(this).balance;
        if (bal < withdrawAmount) {
            revert InsufficientBalance({balance: bal, withdrawAmount: _withdrawAmount});
        }
    }
} 
```
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Account {
    uint public balance;
    uint public constant MAX_UINT = 2**256 - 1;

    function deposit(uint amount) public {
        uint oldBalance = balance;
        uint newBalance = balance + amount;

        // balance + amount does not overflow if balance + amount >= balance
        require(newBalance >= oldBalance, "Overflow");

        balance = newBalance;

        assert(balance >= oldBalance);
    }

    function withdraw(uint amount) public {
        uint oldBalance = balance;

        // balance - amount does not underflow if balance >= amount
        require(balance >= amount, "Underflow");

        if (balance < amount) {
            revert("Underflow");
        }

        balance -= amount;

        assert(balance <= oldBalance);
    }
}
```
For more content, follow me at - https://linktr.ee/shlokkumar2303