Solidity —Part 1- Assert, Require, Revert

Shishir Singh
4 min readApr 15, 2023

Solidity is a programming language used to write smart contracts on the Ethereum blockchain. Smart contracts are self-executing contracts that allow for the automatic transfer of digital assets when certain conditions are met.

In this series, we will cover some of the more tricky areas of Solidity. This series is aimed at Intermediate level of Solidity skills.

In Solidity, three essential functions are used to manage the conditions to conform: assert, require, and revert.

Assert

The assert function checks for conditions that should never be false, such as an internal invariant being violated. If the condition is false, the function will immediately terminate and revert all state changes, including any transferred Ether. For example, in the Validation the contract below, the assert_gas the process will terminate if _value is less than or equal to zero:

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

contract Validation {
event GasConsumed(uint256 gasConsumed, string message);

function assert_gas(uint256 _value) public returns (bool) {
string memory message = "Assert:Value must be greater than 0";
uint256 gasBefore = gasleft();
assert(_value > 0);
uint256 gasAfter = gasleft();
uint256 gasConsumed = gasBefore - gasAfter;
emit GasConsumed(gasConsumed, message);
return true;
}

Gas —Assert success

status true Transaction mined and execution succeed
transaction hash 0x4f6842f05df3a7176aff7bd63cad0f2a42024ac9901c550c1b1aa5137a6cdb8a
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to Validation.assert_gas(uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 28604 gas
transaction cost 24873 gas
execution cost 3669 gas
input 0x439...00001
decoded input {
"uint256 _value": "1"
}
decoded output {
"0": "bool: true"
}
logs [
{
"from": "0xd9145CCE52D386f254917e481eB44e9943F39138",
"topic": "0x2e3e32a19c59b5feea2d5bf8bd9881b5b5f95d280eb922d7a7dcc873b008cb3e",
"event": "GasConsumed",
"args": {
"0": "33",
"1": "Assert:Value must be greater than 0",
"gasConsumed": "33",
"message": "Assert:Value must be greater than 0"
}
}
]

Gas — Assert fails

status false Transaction mined but execution failed
transaction hash 0x1329c1b5352463192835e062ad6b7721d1558b4c8805abffbbd4ae2fe5f2684a
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to Validation.assert_gas(uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 3000000 gas
transaction cost 21738 gas
execution cost 546 gas
input 0x439...00000
decoded input {
"uint256 _value": "0"
}
decoded output {
"0": "bool: true"
}
logs []
val 0 wei

Require

The require function is similar to the assert function, but is used to check for user input errors, such as invalid function parameters. If the condition is false, the function will immediately terminate and revert all state changes. However, any Ether that was transferred will be refunded back to the caller. For example, in the Validation the contract below, the require_gas the function will terminate if _value is less than or equal to zero:

    function require_gas(uint256 _value) public returns (bool) {
string memory message = "Require:Value must be greater than 0";
uint256 gasBefore = gasleft();
require(_value > 0, message);
uint256 gasAfter = gasleft();
uint256 gasConsumed = gasBefore - gasAfter;
emit GasConsumed(gasConsumed, message);
return true;
}

Gas — Require success

status true Transaction mined and execution succeed
transaction hash 0xa4d0d65761104f2c85c44eaf764e7ff684290f8737fd5c2a07d7fa80b3340c96
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to Validation.require_gas(uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 28588 gas
transaction cost 24859 gas
execution cost 3655 gas
input 0x1da...00001
decoded input {
"uint256 _value": "1"
}
decoded output {
"0": "bool: true"
}
logs [
{
"from": "0xd9145CCE52D386f254917e481eB44e9943F39138",
"topic": "0x2e3e32a19c59b5feea2d5bf8bd9881b5b5f95d280eb922d7a7dcc873b008cb3e",
"event": "GasConsumed",
"args": {
"0": "41",
"1": "Require:Value must be greater than 0",
"gasConsumed": "41",
"message": "Require:Value must be greater than 0"
}
}
]

Gas — Require fails

status false Transaction mined but execution failed
transaction hash 0x01999fdeedc53ba76b84063705598f8a9329b8098f8f46c9b5ca34906729a376
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to Validation.assert_gas(uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 3000000 gas
transaction cost 21738 gas
execution cost 546 gas
input 0x439...00000
decoded input {
"uint256 _value": "0"
}
decoded output {
"0": "bool: true"
}
logs []
val 0 wei
transact to Validation.require_gas pending ...
transact to Validation.require_gas errored: VM error: revert.

revert
The transaction has been reverted to the initial state.
Reason provided by the contract: "Require:Value must be greater than 0".
Debug the transaction to get more information.

Revert

The revert function is used to explicitly revert state changes and stop the execution of a function. It is typically used to handle unexpected errors, such as invalid inputs or external contract calls that fail. If the condition is false, the function will immediately terminate and revert all state changes, including any transferred Ether. For example, in the Validation contract below, the revert_gas function will terminate if the _value is less than or equal to zero and revert all state changes:

    function revert_gas(uint256 _value) public returns (bool) {
string memory message = "Revert:Value must be greater than 0";
uint256 gasBefore = gasleft();
if (_value <= 0) {
revert(message);
}
uint256 gasAfter = gasleft();
uint256 gasConsumed = gasBefore - gasAfter;
emit GasConsumed(gasConsumed, message);
return true;
}

}

Gas — Revert success

status true Transaction mined and execution succeed
transaction hash 0x6281605cd64c066a30c0ebf958edb3c7da788d2d5c8f96681098164e2198c3ea
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to Validation.revert_gas(uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 28630 gas
transaction cost 24895 gas
execution cost 3691 gas
input 0xe73...00001
decoded input {
"uint256 _value": "1"
}
decoded output {
"0": "bool: true"
}
logs [
{
"from": "0xd9145CCE52D386f254917e481eB44e9943F39138",
"topic": "0x2e3e32a19c59b5feea2d5bf8bd9881b5b5f95d280eb922d7a7dcc873b008cb3e",
"event": "GasConsumed",
"args": {
"0": "33",
"1": "Revert:Value must be greater than 0",
"gasConsumed": "33",
"message": "Revert:Value must be greater than 0"
}
}
]

Gas — Revert fails

status false Transaction mined but execution failed
transaction hash 0x7175bfdc64ccd28298fc0fc7fc548cfa3b3adc0235ed2b35094967abe6f15191
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to Validation.revert_gas(uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 3000000 gas
transaction cost 22340 gas
execution cost 1148 gas
input 0xe73...00000
decoded input {
"uint256 _value": "0"
}
decoded output {
"0": "bool: true"
}
logs []
val 0 wei
transact to Validation.assert_gas pending ...
transact to Validation.assert_gas errored: VM error: revert.

revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.

In conclusion, the assert, require, and revert functions are crucial tools in Solidity that allow developers to manage the execution of smart contracts and ensure their security and reliability. By using these functions effectively, developers can create decentralized applications that are trustworthy and secure for all parties involved. As blockchain technology continues to evolve and gain popularity, Solidity, and smart contracts will play an increasingly important role in shaping the future of finance and commerce.

In Part 2 we cover Payable, Fallback, and Receive.

--

--

Shishir Singh

Digital Assets, Blockchains, DLTs, Tokenization & Protocols & AI Intersection