Logo

dev-resources.site

for different kinds of informations.

A Walkthrough of Solidity Custom Errors

Published at
12/21/2024
Categories
ethereum
smartcontract
nft
solidity
Author
block_experts_766a3a21915637
Author
28 person written this
block_experts_766a3a21915637
open
A Walkthrough of Solidity Custom Errors

Image descriptionAs blockchain smart contracts developer, efficiency and clarity in smart contract development are always my top priority. Solidity, the most popular programming language for Ethereum smart contracts, introduced custom errors in version 0.8.4 via revert function and make it available in solidity 0.8.26 via require and could be used only via via-ir pipeline, and now available from solidity 0.8.27 in legacy pipeline. This feature allows to optimize gas and improve the readability of error messages. This article provides a comprehensive walkthrough of Solidity custom errors, their advantages, why it must be used, and implementation.


Why Use Custom Errors?

Traditional methods of error handling in Solidity primarily rely on require, revert, and assert statements with strings as error messages. While effective, these methods have limitations:

  1. High Gas Costs: Storing long error strings consumes more gas.
  2. Lack of Structure: Error strings provide limited context and can be challenging to parse programmatically.

Custom errors address these issues by:

  • Reducing gas consumption, as error data is encoded compactly.
  • Allowing developers to define structured errors with parameters, making debugging easier.

Gas Optimization Example

To understand the gas savings, consider the following comparison:

Using require with an Error Message

require(condition, "Insufficient balance for withdrawal");
Enter fullscreen mode Exit fullscreen mode

Using a Custom Error

error InsufficientBalance(address account, uint requested, uint available);

require(condition, InsufficientBalance(msg.sender, requestedAmount, availableBalance));
Enter fullscreen mode Exit fullscreen mode

Gas Cost Analysis

  • require with string: The gas cost increases with the length of the string. For example, a 32-character error message can add 200-300 gas.
  • Custom error: Encodes error data more compactly, reducing gas costs significantly. Using a custom error in this scenario can save ~100-150 gas per revert.

While savings may seem small per transaction, they add up significantly in high-frequency or large-scale dApps.


Syntax and Structure of Custom Errors

Custom errors are defined at the contract level using the error keyword. Here's the basic syntax:

error CustomErrorName(string parameter1, uint parameter2);
Enter fullscreen mode Exit fullscreen mode

You can then use require with the custom error to abort execution and provide specific error details:

require(condition, CustomErrorName("Reason", 42))
Enter fullscreen mode Exit fullscreen mode

Practical Example: Using Custom Errors

Let’s explore a practical example to understand how custom errors work.

Contract: Simple Bank

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

contract SimpleBank {
    mapping(address => uint) private balances;

    error InsufficientBalance(address account, uint requested, uint available);

    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint amount) external {
        uint balance = balances[msg.sender];
        require(amount <= balance, InsufficientBalance(msg.sender, amount, balance);


        balances[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
    }

    function getBalance() external view returns (uint) {
        return balances[msg.sender];
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. Defining the Error:
    The InsufficientBalance error includes the account address, the requested withdrawal amount, and the available balance.

  2. Using the Error:
    In the withdraw function, the contract checks if the requested amount exceeds the balance. If so, it uses revert with InsufficientBalance to provide detailed error data.

  3. Gas Savings:
    Unlike traditional error strings, custom errors reduce the gas cost by encoding error data in a compact form.


Interpreting Custom Errors in Transactions

When a transaction fails due to a custom error, the error details are accessible through the transaction’s revert reason. Tools like Etherscan, Hardhat, and Foundry can decode these errors, enabling developers to debug efficiently.

Enable via-ir in hardhat (for solidity v0.8.6 no need for this from v.8.27)

here is how to enable via-ir pipeline:

const config: HardhatUserConfig = {
  ...
  defaultNetwork: "sepolia",
  solidity: {
    version: "0.8.26", // any version you want
    settings: {
      viaIR: true,
  },

};
Enter fullscreen mode Exit fullscreen mode

Decoding Example:

Using Hardhat, you can decode custom errors as follows:

  1. Run the failing test or transaction.
  2. Use the debug output to inspect the revert reason.
Error: VM Exception while processing transaction: reverted with custom error 'InsufficientBalance'("0xYourAddress", 100, 50)
Enter fullscreen mode Exit fullscreen mode

Best Practices for Custom Errors

  1. Be Descriptive: Define custom errors with meaningful names and parameters.
  2. Group Errors: If a contract has many errors, consider grouping them using comments or organizing them by functionality.
  3. Combine with Events: Use custom errors alongside events for comprehensive debugging and logging.

Conclusion

Custom errors in Solidity are a powerful tool for writing efficient and maintainable smart contracts. By reducing gas costs and improving error transparency, they enable to build optimized and readable smart contracts. Integrate custom errors into your projects today and elevate your smart contract development game!
Here a real example smart contracts that uses custom errors

🌟 Useful Tools for Blockchain Developers


solidity Article's
30 articles in total
Favicon
Have You Fallen for a Phishing Scam? Let’s Talk About It 👀
Favicon
Solidity
Favicon
Why Every Crypto Developer Should Understand Tokenomics 🚀
Favicon
How we used the ERC-2535 Diamonds at Proof of Peacemaking Protocol
Favicon
🔐 Solidity Limitations, Solutions, Best Practices and Gas Optimization 🚀
Favicon
go调用solidity合约新方法
Favicon
⚖️ The Importance of Using ReentrancyGuard in Solidity Smart Contract
Favicon
Formal Verification: An Example
Favicon
OverFlow and UnderFlow causes in Solidity
Favicon
When to Use ERC-721 vs ERC-1155: Choosing the Right NFT Standard
Favicon
Solidity Pattern - Proxy Delegate and Decorator Patterns
Favicon
Solidity Patterns - CEI
Favicon
Foundry vs Hardhat (A story version)
Favicon
Energy NFT Marketplace
Favicon
OverFlow and UnderFlow causes in Solidity
Favicon
🚀 Getting Started with kritisi CLI: An AI-Driven Security Tool for Solidity
Favicon
Formal Verification: The Foundation of Ethereum Smart Contracts
Favicon
The Danger of Randomness in Smart Contracts and its solution
Favicon
What is Reentrancy?
Favicon
Understanding approve and depositCollateral: The Core of ERC-20 Token Transfers in Solidity
Favicon
Ethereum Transaction Calls and State Changes
Favicon
Creating a Toy Solidity compiler and running it in a Toy EVM
Favicon
Send Tokens in Bulk with Low Fees and Fast Delivery: The Ultimate Airdrop Tool for 2024
Favicon
🛡️ Why Using OpenZeppelin in Smart Contracts Is Essential
Favicon
The delegatecall Function in Solidity
Favicon
The delegatecall Function in Solidity
Favicon
A Walkthrough of Solidity Custom Errors
Favicon
How to write dynamic staking smart contract step by step in practice
Favicon
Mainnet Forking in Foundry
Favicon
Every Blockchain Developer Must Know About This Scam!

Featured ones: