Solidity tips and tricks #3: Custom errors

Solidity v0.8 introduced a lot of interesting updates. We already covered the “Unchecked Arithmetic” concept in the first post of this series. Another interesting and handy feature introduced starting from v0.8.4 is “Custom errors”. Let’s explore how custom errors work.

Errors in solidity

When an error occurs in a transaction, it reverts all of the state changes the transaction has proposed ( since solidity is Turing complete ). You can throw an error in solidity using: 

  • require is to validate and enforce a particular outcome for a condition. If the outcome differs from what is specified, it throws an error.
  • revert is similar to require. It is particularly useful when the condition to check is complex.
  • assert is used to check for code that should never be false. Failing assertion probably means that there is a bug.

Quick example code: 

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
contract DemoErrors {
function demoRequire(uint input) public pure {
require(input > 5, “input must be greater than 5”);
}
function demoRevert(uint input) public pure {
if (input <= 10) {
revert(“Input must be greater than 10”);
}
}
function demoAssert(uint input) public pure {
assert(input >=10);
}
}
view raw DemoErrors.sol hosted with ❤ by GitHub

As you can see, we can pass error messages in require (second parameter ) and revert ( first and only parameter ). There are two potential drawbacks:

  • The length of the string is directly proportional to deployment cost.  And since we can pass strings of arbitrary length, there is a chance that we add larger strings in a bid to make error messages “informative”.
  • Generalization is tedious. For example, if we want to change this message dynamically based on some logic in the contract, it’s a bit of extra work.

Custom Errors:

Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries). The syntax of errors is similar to that of events. So you can pass parameters to declared error. Example: 

error Unauthorized(address caller);

Errors can be inherited, but you cannot override them. They are also cheaper when compared to traditional strings as errors. Let’s see an example to understand how errors can be used with revert.

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
contract DemoCustomError {
error Unauthorized();
error myCustomError(string message);
address public owner = address(0x0);
function checkAuthorisation() public view {
if(msg.sender != owner) {
revert Unauthorized();
}
}
function testCustomErrorMessage(string calldata message) public pure {
revert myCustomError(message);
}
}

This is the output for calling the function “testCustomErrorMessage” function”: 

So in short, custom errors introduced by solidity make error reporting cheaper as well as programmatically dynamic, making our solidity code more efficient and structured. For more such content or any questions about blockchains, EVM, and solidity, reach out to me on my socials.

%d bloggers like this: