Differences between assert and require statements in Solidity (Error Handling In Solidity, pt. 4)

Favour AjayeFavour Ajaye
6 min read

In Part 1, we saw the importance of error handling in solidity, potential risks and vulnerabilities, and the impact of error handling on user experience and contract security.

Then we dived deeper into the different types of exceptions that can occur in Solidity contracts, like Assertion Failure, Out-of-Gas Exceptions, Invalid Operations, Revert and Require Statements, External Call Exceptions, Custom exceptions, and Low-Level exceptions, with their code examples in part 2.

We then moved further to the try-catch mechanism and how it improves error handling in Part 3.

Differences between assert and require statements in Solidity

In Solidity, both assert and require statements are used to validate conditions and ensure certain requirements are met within a contract. While they serve similar purposes, there are important differences between the two:

Usage:

  • assert: The assert statement is typically used to check for conditions that should never be false under normal circumstances. It is used to validate internal consistency and invariants within the contract. The primary purpose of assert is to catch programming errors, and it is not intended for handling user or external input validation.

  • require: The require statement is commonly used for input validation and to enforce preconditions. It verifies external inputs or conditions required for the proper execution of the contract. require statements are often used to ensure that function inputs meet certain requirements before proceeding with execution.

Error Handling

  • assert: When an assert statement fails, it indicates an internal error or an inconsistent state within the contract. In such cases, the contract's execution is immediately halted, all state changes made in the current transaction are reverted, and the gas used is not refunded. The purpose of assert is to identify and catch programming errors that should not occur in normal operation.

  • require: When a require statement evaluates to false, it indicates that a condition necessary for the proper execution of the contract has not been met. The contract execution is reverted, all state changes within the current transaction are undone, and the remaining gas is refunded. require is often used to validate user input or enforce contract preconditions, allowing for controlled error handling.

Gas Consumption:

  • assert: Since assert is used to capture internal errors that should not occur under normal conditions, it is not expected to be used for error handling in user input scenarios. Therefore, gas optimization is not a primary consideration for assert statements.

  • require: require statements have gas optimization considerations. If a require statement fails, the remaining gas is refunded, making it a cost-effective way to handle input validation and enforce preconditions in contract execution.

Intended Use:

  • assert: It is primarily used for internal consistency checks, ensuring that assumptions and invariants within the contract are not violated. It is commonly employed during the development and testing stages to catch and identify bugs.

  • require: It is commonly used for input validation, enforcing function preconditions, and ensuring that user-provided data meets specific requirements. require statements are often used to validate function inputs and handle external conditions to ensure correct contract execution.


When to use assert and require statements based on the expected behavior and contract logic

When deciding whether to use assert or require statements in your Solidity contract, it is crucial to consider the expected behavior, contract logic, and the purpose of the validation. Here are some guidelines to help you determine when to use assert and require:

  1. assert Statements:
  • Use assert when validating internal consistency and invariants within the contract.

  • Use it for conditions that should never be false under normal circumstances.

  • Examples include validating critical internal state, ensuring the correctness of calculations, or catching programming errors.

  • assert statements are primarily used during development and testing stages to identify and catch unexpected behavior or inconsistencies.

  • Be cautious when using assert in user input scenarios, as it does not provide a controlled error-handling mechanism and is intended for identifying internal errors rather than handling external conditions.

  1. require Statements:
  • Use require to enforce preconditions and validate external inputs or conditions necessary for correct contract execution.

  • Use it to validate user-provided data, function inputs, or external factors that affect the contract's behavior.

  • Examples include validating input ranges, checking ownership or access control, or enforcing contract preconditions.

  • require statements allow for controlled error handling and provide a mechanism to communicate the reason for the error to users.

  • Consider gas optimization when using require as failed require statements revert the transaction and refund the remaining gas, making it a cost-effective way to handle input validation.

Questions to ask before using assert or require

In general, when determining whether to use assert or require, ask yourself the following questions:

  • Is the validation checking internal consistency or external conditions?

  • Should the condition being checked always be true under normal circumstances?

  • Is the validation primarily used for catching programming errors or for handling external inputs?

  • Do you need controlled error handling and the ability to provide custom error messages?


Examples illustrating the appropriate use of assert and require statements for error handling

Example 1

Use of assert for Internal Consistency Checks

In this example, the assert statement is used to check if the contract has sufficient balance before performing a transfer operation. It ensures the internal consistency of the contract by verifying an invariant (the contract should always have enough balance for the transfer). If the condition fails, it indicates a critical error or inconsistency within the contract, and the execution is halted immediately.

Example 2

Use of require for Input Validation

In this example, the require statement is used to validate the input amount for a deposit operation. It enforces a precondition that the amount being deposited must be greater than zero. If the condition fails, the execution is reverted, and the provided error message is returned to the caller. This ensures that invalid or insufficient amounts are not accepted for the deposit.

Example 3

Combined Use of assert and require

In this example, both require and assert statements are used for error handling. The require statement checks if the sender has enough balance to perform the transfer, providing a custom error message if the condition fails. The assert statement validates the internal consistency by ensuring that the contract has sufficient allowance for the transfer. If any of the conditions fail, it indicates an error, and the execution is halted immediately.


Finally, we have one more part to go. Stay tuned. In the next part, we will be highlighting the importance of providing meaningful error messages to users, techniques for constructing informative error messages in Solidity contracts and best practices for effective error handling in Solidity.


Check out my other articles on Solidity Basics (Solidity Data Types and Operators)**, [solidity inheritance](favourajaye.hashnode.dev/solidity-inheritance), Solidity fallback function and function overloading, Variables and control structures in solidity, Solidity Functions, Libraries in solidity, Abstract contracts and Interfaces in solidity, [Guidelines on becoming a Blockchain Developer in 2023 (Solidity)](medium.com/coinsbench/guidelines-on-becomin..), [What is blockchain?](medium.com/web3-magazine/what-is-blockchain..), [All you need to know about web 3.0](medium.com/web3-magazine/all-you-need-to-kn..), [Solidity: Floating points and precision](medium.com/@favoriteblockchain/solidity-flo..), and others

Click here to see the Github repo for this 100 days of solidity challenge.

Don’t forget to follow me, put your thoughts in the comment section, and turn on your notifications.

0
Subscribe to my newsletter

Read articles from Favour Ajaye directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Favour Ajaye
Favour Ajaye

smart contract developer