In this track: Write and read Solidity
advanced · 4 MIN READ

Custom errors in Solidity

Typed failures can encode useful context compactly.

LET’S PICTURE IT

A rejection form can identify a specific rule and include the values relevant to the failed request.

SEE IT FOR YOURSELF
Follow a revert and decode its error dataStep 1 / 4
Follow a revert and decode its error dataRequested actionTransfer 100 raw unitsExample inputsAvailable balance40 raw unitsCheck the ruleA deliberately failing local scenario, not a live transactionCondition fails100 > 40Request rejectedRollbackNo successful transferConsumed gas still mattersTop-level failure and a caught nested failure have different contextsError selector0x08c379a04 bytesMessage tailNot enough tokensDynamic string encodingCustom errors and Panic use different selectors and schemasDecoded messageNot enough tokensA diagnostic clueFurther evidenceCaller and code pathRelevant stateError bytes can be constructed by code; decoding is not authentication

This fictional call requests a transfer of one hundred raw units while the relevant balance is forty.

Animated local teaching model. No wallet, RPC or live blockchain data. Some labels and hashes are abbreviated for readability.

Declare a schema for failure

A custom error has a name and typed parameters. Its ABI representation uses a four-byte selector followed by encoded arguments, resembling function-call framing.

Use it on the actual path

The declaration alone does not enforce a condition. Code must check the condition and revert with the error when appropriate.

Decode with the correct declaration

A decoder needs the error interface to interpret custom arguments. The selector is short and can collide; bytes do not provide a globally authenticated error identity.

Investigate beyond the name

An Unauthorized error can be useful evidence, while the caller context and ownership state explain why the check failed. The local decoder does not fetch those facts.

Read the example

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

contract LearningExample {
    error TooLarge(uint256 supplied);

    function bounded(uint256 x) external pure returns (uint256) {
        if (x > 100) revert TooLarge(x);
        return x;
    }
}

Try the same error declaration in the revert decoder with encoded sample data.

TURN UNDERSTANDING INTO PRACTICEOpen the Revert decoder →
QUICK CHECK · NO PRESSURE

Does declaring an error automatically perform its permission check?

Your progress stays in this browser.
Keep exploring the original referenceSolidity documentation ↗

Original explanations by EtherTools. Examples are educational and source-linked; this site is independent of the Ethereum Foundation. Our approach.