This article introduces the usage of custom error in Solidity, including ways to define errors, usage, and error handling.

Usage

This feature was added after Solidity v0.8.4, which can use a custom error to return the error reason. In the past, we usually used the following methods to throw errors:

1
2
3
4
5
6
7
require(shouldPass, "MyError");

// or

if (!shouldPass) {
revert("MyError");
}

Custom error is used as follows:

1
2
3
4
5
6
7
8
9
10
11
12
// Define custom error
error MyError();

contract MyContract {
function test() external {
// ...
if (!shouldPass) {
revert MyError();
}
// ...
}
}

Custom error can also have parameters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Define custom error
error MyErrorWithArgs(uint status);

contract MyContract {
function test() external {
// ...
if (case1) {
revert MyErrorWithArgs(0);
} else if (case2) {
revert MyErrorWithArgs(1);
}
// ...
}
}

The following usage can be thought of as the same

1
2
3
4
5
revert("MyError");

// equal to
// error Error(string reason);
// revert Error("MyError");

But actually the names of Error and Panic are special names and cannot be used.

Try-Catch

It is more complicated to use try-catch to catch custom error in the contract. Currently, the following methods can be used:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
contract TryCatch {
MyContract myContract = new MyContract();

function execute() external {
try myContract.callSomeMethod() {
// success
} catch (bytes memory reason) {
bytes4 selector = bytes4(reason);
if (selector == bytes4(MyError.selector)) {
// when MyError()
} else if (selector == bytes4(MyError.selector)) {
// when MyErrorWithArgs(uint)

// If you want to check status
bytes32 hash = keccak256(reason);
if (hash == keccak256(abi.encodeWithSelector(MyErrorWithArgs.selector, 0))) {
// when MyErrorWithArgs(0)
} else if (hash == keccak256(abi.encodeWithSelector(MyErrorWithArgs.selector, 1))) {
// when MyErrorWithArgs(1)
}
} else {
// others
}
}
}
}

Pros and Cons

Pros

  • The compiled contract size is relatively small.
  • Slightly reduced gas consumption.
  • It’s easy to use parameters.

Cons

  • Node support is required: For example, Ganache for local development does not support it. The error reason cannot be parsed.
  • Requires block explorer support to display: At present, browsers seem to be unable to parse this type of error.
  • The support of web3.js and ether.js is not complete, and additional processing is required.

Further Reading

Using Ethers.js to Parse Custom Error
Using Web3.js to Parse Custom Error