3.1 Solidity Versions
The Solidity
language has evolved considerably in the last several years. There have been many features added, some of them removed. Security has been improved in several cases, optimizations have been made.
As a result, there are many versions of Solidity
that are available for projects and developers to choose from. At least one version is released every few months that make some optimizations and fixes some bugs a couple of breaking changes are introduced every year or so. As a result, the question is always about which version of the Solidity
compiler to use for a particular project, so that the best combination of features and security aspects are considered.
The older compiler versions are time tested, but they have bugs. The newer versions have the bug fixes which is good, but they may also have new bugs which have been undetected so far.
The older versions have lesser features compared to the newer versions ( that usually have more features). Some of these are language level features that are visible syntactically, others are semantic changes, others are security features and some others are optimizations that are not very visible.
As a result, the choice of an optimal version of the compiler for a particular project is always a tricky thing. This has to take account not just the functionality, but also the security aspect. As a result, there is a trade-off to be made, there are risks as well as rewards. As of this point many of the projects are transitioning to the Solidity
version 0.8.0
and beyond, because among other things, this version has introduced default arithmetic checks for underflow and overflows.
These aspects of security and functionality, the range of choices available across the various Solidity
compiler versions, have to be kept in mind when determining which version to use for a particular project.
Unlocked Pragma
Remember that Solidity
supports the concept of pragma
directives and one of them is related to the Solidity
compiler version, that can be used with this smart contract.
There are many aspects related to that fragment directive, but the one that is relevant from a security perspective, is the concept of that pragma
being unlocked or floating and what this means is that in the pragma
directive that specifies the compiler version, if the caret (^
) symbol is used, then it is referred to as being unlocked.
What this means, is that the use of this caret symbol, specifies that any compiler version starting from the one specified in that pragma
directive all the way to the end of that breaking version can be used to compile this smart contract. As an example, if the pragma
directive is ^0.8.0
it means that any compiler version from 0.8.0
all the way to the last version in the 0.8.z
range can be used according to this pragma
for compiling this smart contract.
This becomes interesting from a security perspective. The use of such an unlocked or floating pragma
allows one Solidity
compiler version to be used for testing, but potentially, a different one that is used for compiling the contracts while being deployed.
This aspect of using a different version for testing and deployment is risky from a security perspective. That's because one could test with a totally different set of compiler features and security checks, the newer version or a different version that is used for deployment may support a different set of features and a different set of security checks, so this mismatch between testing and deployment is allowed by the use of this unlocked pragma
and hence is not recommended to be used.
So what is recommended is to lock
the pragma
by not using the caret symbol in that pragma
directive, this will enforce that the same compiler version is used for testing as well as for deployment.
Multiple Pragma
Another security aspect related to the use of the solution compiler pragma
in contracts is the use of different pragmas across different contracts within a single project.
Remember that the pragma
applies only to the contract where it is used so. If there are different multiple contracts that are used within a single project, then each one of them could have a different pragma
specifying a different compiler version.
The reason why this is not recommended is because these different compiler versions like we just discussed can have different bugs, different bug fixes, different features and even different security checks across the versions. This will result in different components of the application having different security properties which is not desirable.
So from a security perspective, what is recommended is to use the same pragma
across all the different contracts that form that smart contract application. This will result in all of them having the same set of bugs, features and security checks which can be accounted for while one is testing that smart contact application.
Last updated