Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
LABS
Glossary

Custom Errors

A Solidity feature that allows developers to define and revert with custom, gas-efficient error data instead of revert strings.
Chainscore © 2026
definition
SOLIDITY FEATURE

What are Custom Errors?

A gas-efficient and expressive mechanism for defining and throwing application-specific error conditions in Solidity smart contracts.

Custom errors are a feature introduced in Solidity v0.8.4 that allow developers to define their own error types with descriptive names and parameters, which can then be used with the revert statement. Unlike the older require statement with a string message, custom errors are defined using the error keyword (e.g., error InsufficientBalance(uint256 available, uint256 required)). When the contract reverts using a custom error (revert InsufficientBalance(balance, amount)), only the error's selector (a 4-byte identifier) and the encoded parameter data are passed to the caller, resulting in significant gas savings compared to storing and passing dynamic string messages.

The primary advantage of custom errors is their efficiency. Deploying a contract with string error messages stores those strings permanently on-chain, incurring a one-time deployment cost and a runtime cost every time they are used. Custom errors, however, are defined only by their signature in the contract's ABI; the descriptive name and parameter structure are known off-chain by tools like Etherscan, which can decode and display them. This makes them a best practice for gas optimization without sacrificing debuggability for end-users and developers interacting with the contract.

From a development perspective, custom errors enhance code clarity and type safety. They function similarly to custom exception types in other languages, allowing for more structured error handling. Developers can define multiple specific errors (e.g., Unauthorized, InvalidDeadline, TransferFailed) and catch them off-chain using the contract's ABI. This is a marked improvement over parsing generic revert strings. Furthermore, because they are a compile-time feature, using an undefined error will cause a compilation error, preventing runtime typos.

A key technical detail is how custom errors interact with the Ethereum Virtual Machine (EVM). When a revert with a custom error occurs, the EVM uses the REVERT opcode, passing the ABI-encoded data of the error. This data is returned to the caller and can be decoded if the error's signature is known. This mechanism is also foundational for more advanced patterns, such as facilitating ERC-4337 Account Abstraction validation or creating complex, nested error conditions that can be cleanly propagated and inspected by off-chain infrastructure and user interfaces.

how-it-works
SOLIDITY ERROR HANDLING

How Custom Errors Work

Custom errors are a gas-efficient Solidity feature introduced in v0.8.4 for defining and throwing revert conditions with descriptive data.

A custom error is a user-defined type in Solidity that provides a structured, low-cost alternative to the require statement with a string message. Defined with the error keyword, it allows developers to revert transactions while passing arbitrary data, such as an error identifier and relevant parameters, which is then ABI-encoded and returned to the caller. This mechanism is significantly more gas-efficient than legacy string messages because it avoids the cost of storing and hashing long strings on-chain.

The primary advantage of custom errors is their gas optimization. When a transaction reverts, only the 4-byte selector of the error and the encoded arguments are passed in the revert data, unlike string messages which require expensive storage. For example, error InsufficientBalance(uint256 available, uint256 required); defines an error that can be called with revert InsufficientBalance(balance, amount). This provides clear, machine-readable failure information to off-chain clients without incurring the high gas overhead of a descriptive string.

To use a custom error, you must first declare it, typically at the contract level or in a file-level error statement. It is then invoked using the revert statement. Off-chain applications can decode the revert data by matching the error's signature, allowing for precise error handling in front-ends and indexers. This creates a clean contract interface where failure modes are explicitly defined, improving code auditability and integration. Common use cases include input validation, access control checks, and state condition enforcement where specific failure data is valuable.

key-features
CUSTOM ERRORS

Key Features & Benefits

Custom errors are a Solidity feature that allows developers to define and use their own error types, providing a gas-efficient and descriptive way to revert transactions.

01

Gas Efficiency

Using revert with a custom error consumes significantly less gas than the older require statement with a string message. This is because the error type is encoded as a 4-byte selector, while strings are ABI-encoded and stored on-chain. For example, revert InsufficientBalance() is cheaper than require(balance >= amount, "Insufficient balance").

02

Named Parameters & Data

Custom errors can accept parameters, allowing developers to pass dynamic data about the failure. This provides more context for off-chain debugging and frontend applications. For example:

  • error InsufficientBalance(address user, uint256 available, uint256 required);
  • revert InsufficientBalance(msg.sender, balance, amount); The error data is ABI-encoded and can be decoded by clients.
03

Improved Debugging

By using distinct, descriptive error names, developers and users can quickly identify the exact cause of a transaction failure. This is a major improvement over generic revert strings. Tools like block explorers and development frameworks can parse and display these named errors, making contract interaction and auditing more transparent.

04

Contract Interface Clarity

Declaring custom errors at the contract level serves as formal documentation for the specific failure conditions the contract can encounter. This makes the contract's ABI more informative, as the possible error signatures are part of the interface. It helps other developers understand the expected behavior and failure modes without scanning the entire codebase.

05

Comparison: Error vs. Require

Custom Error (Solidity >=0.8.4):

  • error Unauthorized(); ... revert Unauthorized();
  • Lower gas cost, can include parameters, defined in contract.

Require with String:

  • require(msg.sender == owner, "Unauthorized");
  • Higher gas cost, static string, no structured data.

Custom errors are the modern, recommended pattern for all new development.

06

Integration with Try/Catch

Custom errors are fully compatible with Solidity's try/catch statement. This allows a calling contract to gracefully handle specific failures from an external call. You can catch a custom error by its type, enabling more robust and granular error handling logic within smart contract systems. Example: try otherContract.action() catch (InsufficientBalance memory err) { ... }

SOLIDITY ERROR HANDLING

Custom Errors vs. Revert Strings: A Comparison

A technical comparison of the two primary methods for reverting transactions and providing failure information in Solidity smart contracts.

FeatureCustom Error (Solidity >=0.8.4)Revert String (require/revert)Legacy Assert

Gas Cost on Revert

~100-200 gas (deployment)

~20k+ gas (deployment & execution)

All gas consumed

Contract Bytecode Size

Minimal increase

Significant increase per string

Minimal increase

Error Information

Named error type + encoded parameters

Human-readable string message

Panic code (0x01, 0x11, etc.)

Parameterization

Off-chain Decoding

Typed Error Handling

Recommended Use Case

All production reverts

Simple prototypes, debugging

Internal invariants only

ecosystem-usage
CUSTOM ERRORS

Ecosystem Usage & Adoption

Custom errors are a Solidity feature (introduced in v0.8.4) that allows developers to define and revert with gas-efficient, descriptive error types, replacing generic require statements with string errors.

01

Core Definition & Syntax

A custom error is a user-defined type declared with the error keyword, used with the revert statement. It provides a structured, low-cost alternative to require(condition, "description").

  • Declaration: error InsufficientBalance(uint256 available, uint256 required);
  • Usage: if (balance < amount) revert InsufficientBalance(balance, amount);
  • Gas Efficiency: Consumes significantly less gas than equivalent string error messages, as the error signature (4-byte selector) is stored on-chain, not the full string.
02

Primary Use Cases & Benefits

Custom errors are deployed for input validation, state checks, and access control where clarity and gas optimization are critical.

  • Gas Savings: The primary driver for adoption; reverting with a custom error costs ~90% less gas than an equivalent error string.
  • Improved Debugging: Provides structured data (parameters) in transaction revert traces, making failures easier to diagnose off-chain.
  • Contract Upgrades: Error types can be added in later versions without breaking existing integrations that only check for revert conditions.
03

Adoption in Major Protocols

Leading DeFi and infrastructure projects have widely adopted custom errors for core contract logic.

  • Uniswap V4: Uses custom errors like InvalidPool, LockFailure, and CurrencyNotSettled throughout its hook and pool management system.
  • OpenZeppelin Contracts: Libraries like @openzeppelin/contracts use errors such as ERC20InsufficientBalance and OwnableUnauthorizedAccount.
  • Compound Finance & Aave: Implement errors for interest rate model calculations and liquidity checks to minimize gas costs for users.
04

Developer Tooling & Standards

Ecosystem tooling has evolved to parse and display custom errors for developers and end-users.

  • Ethers.js & Viem: These libraries decode custom error selectors and parameters from failed transactions, presenting them in human-readable form.
  • Hardhat & Foundry: Testing frameworks have built-in support for expecting specific custom error reverts in unit tests (e.g., vm.expectRevert).
  • Block Explorers: Etherscan and others decode and display custom error names and arguments in transaction receipts.
05

Comparison to Require/Assert

Custom errors differ fundamentally from older Solidity error-handling methods.

  • vs. require(condition, "string"): Custom errors are cheaper on deployment and runtime because the string data is not stored in bytecode. They also allow parameterized data.
  • vs. assert(condition): assert is for internal invariants and consumes all remaining gas on failure, while custom errors (used with revert) refund remaining gas.
  • Error Signature: A custom error is identified by its 4-byte selector (first 4 bytes of keccak256("ErrorName(type)")), which is logged in the transaction receipt.
06

Best Practices & Security Notes

Effective use of custom errors involves careful naming and parameter design.

  • Descriptive Naming: Use names like Unauthorized, InvalidInput, or Overflow that clearly indicate the failure mode.
  • Parameter Selection: Include relevant state variables or arguments (e.g., uint256 actualValue, address caller) to aid off-chain debugging.
  • Security Consideration: The error type and parameters are not stored on-chain after the transaction; they are only emitted in the revert reason. Do not rely on them for on-chain logic.
  • Backwards Compatibility: Interfaces or abstract contracts should declare expected custom errors to guide integrators.
security-considerations
CUSTOM ERRORS

Security Considerations & Best Practices

Custom errors in Solidity are a gas-efficient way to provide detailed revert reasons, but their implementation requires careful planning to avoid security pitfalls and ensure effective debugging.

01

Gas Efficiency vs. Debugging Clarity

While custom errors save significant gas compared to require statements with string messages, they can obscure debugging. Off-chain tools must map the 4-byte selector (e.g., 0x12345678) back to the error name. Ensure your development and monitoring stack supports this mapping for effective incident response.

  • Gas Savings: Reverts with custom errors cost ~~50-100 gas, versus ~20,000+ gas for revert strings.
  • Tooling Dependency: Debugging requires the contract's ABI or source code to decode the error.
02

Avoid Information Leakage

Custom errors can inadvertently expose sensitive contract state or business logic. The error parameters are visible on-chain in the revert data.

  • Example Risk: Reverting with InsufficientBalance(userBalance, requiredAmount) publicly reveals a user's balance.
  • Best Practice: Use generic error types for access control failures (e.g., Unauthorized()) and avoid passing private data as parameters.
03

Consistent Error Hierarchy

Define a clear and consistent error hierarchy to prevent ambiguity and improve maintainability. Group related errors within libraries or inherited contracts.

  • Library Pattern: Define common errors in a base library (e.g., Errors.sol) using error InsufficientAllowance();.
  • Inheritance: Child contracts can use parent contract errors, ensuring uniform error signatures across the system.
  • Naming Convention: Use descriptive, verb-noun names like TransferFailed, InvalidSignature.
04

Testing and Validation

Thoroughly test custom error reverts. Since they do not return strings, standard assertion methods in testing frameworks need to be adapted to check for specific error selectors.

  • Foundry Example: Use vm.expectRevert(MyContract.CustomError.selector);.
  • Hardhat Example: Catch the revert and decode the data using the contract interface.
  • Coverage: Ensure test suites validate all possible error conditions and that the correct error type is thrown.
05

Interface and Upgrade Compatibility

Adding, removing, or changing custom errors is a breaking change for interfaces and upgrades. The 4-byte selector is derived from the error name and parameter types.

  • Breaking Change: Modifying an error's signature will change its selector, breaking off-chain integrations that listen for it.
  • Upgrade Strategy: For upgradeable contracts, consider errors as part of the public API. New errors should be additive where possible.
06

Frontend and Monitoring Integration

Ensure your application frontend and monitoring services (like Chainscore) can properly interpret custom errors. This requires the ABI to be available for decoding transaction revert reasons.

  • User Feedback: Map error selectors to user-friendly messages in your UI.
  • Analytics: Monitoring dashboards should decode and categorize failures by error type to track the health of specific contract functions.
  • Documentation: Publicly document all custom errors and their meanings for integrators.
SOLIDITY

Common Misconceptions About Custom Errors

Custom errors are a powerful Solidity feature for efficient and expressive error handling, but several persistent myths can lead to suboptimal or insecure implementations. This section debunks the most common misunderstandings.

While custom errors are significantly more gas-efficient than require with a string message, they are not a simple drop-in replacement. A custom error is a distinct revert type that allows you to pass structured data, enabling off-chain tools to decode the precise failure reason programmatically. This is a qualitative improvement in developer experience and debugging, not just a quantitative gas saving. For example, revert InsufficientBalance(balance, amountRequired); provides actionable data, whereas require(balance >= amountRequired, "Insufficient balance"); provides only a static string.

CUSTOM ERRORS

Technical Deep Dive

Custom errors are a low-level, gas-efficient way for smart contracts to revert with descriptive failure information, replacing the older `require` and `revert` statements with string messages.

Custom errors are a Solidity feature (introduced in v0.8.4) that allow developers to define and revert with custom, named error types instead of using string descriptions. They work by defining an error with the error keyword, which can include parameters, and then using the revert statement to trigger it. For example, error InsufficientBalance(uint256 available, uint256 required); can be reverted with revert InsufficientBalance(balance, amount);. This is more gas-efficient than string messages because the error signature and its arguments are encoded using ABI encoding (abi.encodeWithSignature) and only the 4-byte selector and encoded arguments are stored on-chain, avoiding the cost of storing lengthy strings.

CUSTOM ERRORS

Frequently Asked Questions (FAQ)

Custom errors are a Solidity feature that allows developers to define and use their own, more efficient and informative error types. This section answers the most common questions about their implementation, benefits, and best practices.

Custom errors are a Solidity feature, introduced in version 0.8.4, that allow developers to define their own error types with descriptive names and optional parameters to provide more informative and gas-efficient failure conditions than the older require statement with a string message. They are declared using the error keyword and are used with the revert statement. For example, error InsufficientBalance(uint256 available, uint256 required); defines a custom error that can be reverted with revert InsufficientBalance(balance, amount);, providing clear, structured data about the failure.

ENQUIRY

Get In Touch
today.

Our experts will offer a free quote and a 30min call to discuss your project.

NDA Protected
24h Response
Directly to Engineering Team
10+
Protocols Shipped
$20M+
TVL Overall
NDA Protected direct pipeline