Smart contract security: Solidity versions (in)compatibility
For Solidity smart contract developers, it’s well known that the language still doesn’t have a major version. Created specifically for EVM-compatible smart contracts, Solidity is actively developing and undergoing very significant changes in the process. In this article, we’ll discuss the main changes to the language and, more importantly, see why you’d better avoid using different versions of Solidity within the same project.
Silent math changes
When you see compiler errors, that’s not a bad thing; on the contrary, it allows you to do something about them. It’s much worse when the compiler doesn’t show you an error when in fact it exists.
One of the main subsections of changes that shows the obvious complexity of interoperability between code written in different versions of the language is silent changes in semantics. This section lists changes in which existing code begins to behave differently without the compiler notifying you. In this case, the conclusion here is pretty obvious: your code may not work the way you expect it to.
For example, let’s take the most sensitive part of smart contracts code: the math. One of the silent changes in Solidity 0.8.0 is the switch to right associative exponentiation. The expression a**b**c in Solidity 0.8.0 is parsed as a**(b**c) instead of (a**b)**c in the previous version.
Let’s explain this change with a simple example: let’s say your code has a = 2, b = 3, c = 4. In version Solidity 0.7. you expect the result a**b**c for you to be, logically, (2**3)**4 = 8**4 = 4096, and to optimize your code you put a small data type for the variable that will store this value. In Solidity 0.8., 2**3**4 = 2**(3**4) = 2**81 = 2.4178516392292583e+24 = 2.4178516392292583 * 10**24. Unexpected, right? Your storage variable is unlikely to handle such a significant difference, not to mention the computational logic of your contract as a whole.
Checked Arithmetic & SafeMath
One of the major new features of Solidity 0.8.0 — Checked Arithmetic, has 3 sub-features:
- Revert on assertion failures and similar conditions instead of using invalid opcode.
- Checked arithmetic, i.e., revert on overflows, underflows etc.
- unchecked blocks.
Previously, internal errors like division by zero, failing assertions, array access out of bounds, etc., would have resulted in an invalid opcode being executed. The problem with invalid opcode is that, unlike revert opcode, it consumes all available gas. This makes it very expensive, and you should try to avoid it.
In Solidity 0.8., these kinds of critical errors are distinguished as they lay within the domain of the smart contract developer. The revert opcode is used, but provides different error data so that static (and dynamic) analysis tools can easily distinguish them.
Thus, starting from 0.8.0 Solidity tracks underflow / overflow, making the use of SafeMath unnecessary. Yet, using SafeMath still makes sense if you know how to redefine an operation in a more profitable way. However, the SafeMath version for Solidity 0.8. does not have the overflow/underflow checks which are now contained in Solidity versions 0.8.
Since checked arithmetic is more gas-expensive and sometimes you really need the wrapping behavior, unchecked { … } block is provided in Solidity 0.8. for the wrapping arithmetic usage. So operations inside the unchecked { … } block use wrapping arithmetic.
So, are the different Solidity version smart contracts compatible?
What can we say about the Solidity version compatibility (with regard to the SafeMath library)? Assuming you simply bind the smart contracts on different versions of Solidity, they will work as intended. But they cannot be compiled as a single project and filled with one set of settings.
Then, when making changes to contracts, if you need to use something from the SafeMath library methods, problems arise, because the library is designed to allow you to import methods from within it.
But if you have different versions of Solidity and, as a result, a ‘fragmented’ project, you will need to import it from an external smart contract. Your system will be less handy, more complicated, and wherever there is complexity and inconvenience, bugs tend to appear — and they’re often hard to spot.
About SmartState
Launched in 2019 and located in Dubai, SmartState provides enterprise level of Web3 security and is retaining the place of one of the leading DeFi security auditing companies. We carry out tests of security of the code core, smart contracts and blockchain for all types of errors or vulnerabilities.
We specialize in manual testing, so the SmartState’s tech team of white-hat security professionals carefully measures up a project’s git and supports clients with guidelines and recommendations for the further advancement.
Our security audit reports review the threats and vulnerabilities with which codebases may be exploited in the future, because the network achieves scalability and expands to accommodate more use cases and functionality.
Keep up to date with all the SmartState news & events, follow us on social media: