Solidity gas efficient technique during error handling.

Solidity gas efficient technique during error handling.

Can we really save gas using this technique?

Introduction

Solidity is a popular programming language used for developing smart contracts on the Ethereum blockchain. As with any programming language, errors can occur during the execution of Solidity code. However, when it comes to smart contracts, errors can have serious consequences such as loss of funds or manipulation of contract logic. Therefore, it is important to handle errors effectively in Solidity to minimize potential risks and ensure the smooth operation of the contract.

This can be achieved through various techniques and in this article, we are going to compare two techniques; using require and using custom errors with revert among other techniques. We aim to understand which technique is more gas efficient.

What is the require keyword?

Require keyword is used in Solidity to ensure certain conditions are met before the program execution proceeds. It takes an expression that has to evaluate to be true before the execution proceeds.

What is the revert keyword?

This is used to stop the execution of a function and undo the changes made to the state of the contract in case some conditions are not met. Learn more on require and revert.

Sample code

In this article, we will use analyze the gas costs when using the two techniques during error handling and conclude which one is more gas efficient. For this, we are creating two contracts where we will implement two different functions; one utilizing the require keyword and the other utilizing the revert keyword.

contract usingRequire{
    function reqTest() public payable{
        require(msg.value > 1, "VeryLowPrice");
    }
}

The second contract.

contract usingRevert{
    error VeryLowPrice();
    function revTest() public payable{
        if(msg.value < 1) revert VeryLowPrice();
    }
}

In the above contracts, for the functions to succeed, we set a condition to ensure that the amount of ether sent along is always greater than zero, otherwise, the functions will fail.

Testing

Now we are going to test the two contracts and run the two functions respectively. We are interested in three values; the deployment cost, the cost when the function runs successfully and the gas cost in case of function failure.

Open your Remix IDE, copy and paste the first contract usingRequire and deploy it. We will call the function once with some test ether and the second time without ether. This will cause the function to succeed in the first instance and fail in the second. Note down the gas costs.

// usingRequire contract
                  //transaction cost
//Deploy                113317         
//Success               21184
//Failure -             21473

Next, repeat the steps above using the usingRevert contract and note the gas costs.

// usingRevert contract
                  //transaction cost
//Deploy                86585         
//Success               21184
//Failure -             21222

Comparing the values from the two deployments, we notice that the gas cost of usingRevert contract is less than that of usingRequire in the two instances;

  1. On deployment.

  2. On failure.

The high cost of deployment in the usingRequire contract arises from the fact that you have to save the error "VeryLowPrice" string in the contract, and we know that strings are not gas efficient. It is therefore always recommended to use custom errors with revert as it is more gas efficient than using require.

Conclusion

You have seen that using custom errors with revert can save a lot of gas on deployment and when the conditions are not met.