Rob Behnke
April 5th, 2021
Smart contracts lie at the heart of DeFi and other blockchain-based solutions. The massive amounts of value that these contracts control means that the impact of programming errors and vulnerabilities can be significant.
Smart contracts can contain a number of different types of vulnerabilities. One concept that Solidity developers commonly struggle with is how to properly handle errors in smart contracts hosted on the Ethereum network.
Smart contracts are programs, and, like in any program, errors can occur. This makes error handling code an essential part of any smart contract.
One of the challenges of error handling in Solidity is that developers have two ways of implementing it. When writing code that integrates with other smart contract functions, it is important to know if they are using reversion or return values to manage error cases.
One option for a failed function call in Solidity is to revert. A reversion essentially signals that the code suffered from an unrecoverable error.
If a function reverts in Solidity, the entire execution state of the transaction is rolled up. This makes it as if the transaction containing the call to the failed function never happens. However, the account performing the transaction still forfeits their transaction fees because the nodes in the blockchain network still expended resources trying to run it.
Reversion is probably the safer of the two options for error handling. If a function reverts, there is no opportunity for the calling function to “recover” from the error. This reduces the probability that a smart contract will end up in an invalid state where the called function failed without the calling function noticing.
The other option for error handling in Solidity is to use function return values. A function can return a value of true if it succeeds, or false if it does not.
This approach to error handling provides a more stable and usable system. Depending on the error that the called function experiences, it may be possible for the calling function to recover. If not, the calling function may be able to fail gracefully, preserving any previous, successful actions that were not impacted by the failure of the called function.
Solidity has two methods of handling errors for a reason. Both of them are valid and have their advantages and disadvantages. The right choice for a particular smart contract can depend on its function and norms within the space.
For example, the use of reversion is the more common option for ERC20 tokens because that is how OpenZeppelin implemented its ERC20 token.
However, even if a smart contract has selected a standard for implementing error handling (i.e. always reverting or always returning false), it is best practice to always perform checks on return values for function calls.
Even if error handling code triggered by a return value of false should never be reached, it’s better to have it and not use it than to not have it if something goes wrong. Assuming that a called function will revert on failure has enabled a number of smart contract hacks, including that of the ForceDAO DeFi aggregator.
Smart contract platforms and languages – such as Ethereum and Solidity – are relatively new. Many developers have not had the opportunity to learn the quirks of these tools to the same degree as they have for more established platforms.
As a result, smart contract vulnerabilities are common, and exploiting them can lead to significant losses. For this reason, it is always best to undergo a comprehensive security audit before launching any smart contract on the blockchain, especially if it is designed to store and process large amounts of cryptocurrency.
To book a consultation with a Halborn blockchain security rep, get in touch at halborn@protonmail.com.