Generally, you should always only use the latest released version available, no prior version whatsoever.
As far as I know, there has not been major exploits caused by a Solidity compiler error ever. Thus, the only non-subjective historic data point we have is that "any Solidity compiler version has always been safe."
Personally I prefer the major version that is one step behind the latest major, as major changes 0.7 -> 0.8 include more changes and more changes are likely to introduce more bugs.
However, some Solidity versions are objectively safer, like Solidity 0.8 because it includes "no unsafe math by default" semantics.
The article is fairly old. I'd suggest taking a look at the current docs on Contract Medatata. They contain these notes:
The CBOR mapping can also contain other keys, so it is better to fully decode the data instead of relying on it starting with 0xa264
. For example, if any experimental features that affect code generation are used, the mapping will also contain "experimental": true
.
The compiler currently uses the IPFS hash of the metadata by default, but it may also use the bzzr1 hash or some other hash in the future, so do not rely on this sequence to start with 0xa2 0x64 'i' 'p' 'f' 's'
. We might also add additional data to this CBOR structure, so the best option is to use a proper CBOR parser.
In 0.4.24 metadata used to contain only the Swarm hash, which is why the starting byte was 0xa1
. The three higher bits say that it's a map (101
= 5
= map in CBOR) and five lower ones say that the map contains only one key (00001
= 1
). In contracts compiled with later versions the map contains 2 items (IPFS hash and the compiler version) which is why it changed to 0xa2
.
The following byte (0x65
) is packed in a similar way - it represents the type and the length of the first mapping key. It changed to 0x64
because the Swarm hash stored under bzzr0
key has been replaced with an IPFS hash stored under a key that is one byte shorter (ipfs
).
For robust detection it's best not to make too many assumptions about how this metadata is structured. Use a heuristic to detect where it starts but then use a proper CBOR parser to decode it. I think it might be best to look only for keys and ignore the type/length bytes. Looking at CompilerStack::createCBORMetadata()
in solc 0.8.9, I see just a few possibilities:
ipfs
bzzr1
experimental
solc
bzzr0
(was present in older versions)
Changes to metadata are always listed in compiler's changelog so keep an eye for newer versions but for the existing ones this should be about it.
Also, you only really need to strip this from the bytecode you get from the blockchain. For the sources you are compiling yourself you can use the --metadata-hash none
flag to get bytecode without a metadata hash.
Having said that, I'd strongly recommend not to ignore metadata during verification. If you use the JSON input that the compiler accepts (rather than flattened sources) and use the right version of the compiler, you should really get the same exact bytecode, including metadata hash embedded in it. Metadata contains hashes of all source files, their paths and compiler options used to build the bytecode so if you ignore these differences, you'll be potentially accepting modified sources - files with misleading comments, completely different variable and contract names, changed licensing info or even extra code that got optimized out. Actually, having the metadata JSON and original sources is always enough to recreate compiler input that exactly reproduces the bytecode. This is why it's recommended to keep and publish the metadata (e.g. using Sourcify).
The practice of ignoring metadata is outdated and comes from the limitations of older versions of the compiler and the verification tools. For example, in the past etherscan required you to submit a single source file, which is why a common strategy used by verification tools is to combine all your files into one. This requires an assumption that you can simply replace any import with the content of the corresponding file. This might have been true in the past but is not guaranteed to work now and new features that depend on separation between source units are planned. Since version 0.4.11 the compiler provides a standardized JSON interface and etherscan supports it too and this is the safer way to do verification.
Best Answer
Mist / Ethereum Wallet now has a built-in compiler that is not very well documented beyond screenshots in the tutorials in order to create, compile, and deploy contracts. However, the version of Mist's compiler and whether or not it is optimized is...hard to figure out.
Go to the Mist releases page.
Click on the release you are using. ie: 0.5.2
Click "CODE" at the top. example link
Click `package.json'. example link
Look for
"solc": "^0.X.X-X",
. That is the version. So for Mist 0.5.2, the solc version is 0.2.1-1.However, this does NOT necessarily solve your problem with getting verified on EtherScan. I cannot get the token code to match either, no matter what I tried (and I tried a lot). See the bottom of this comment if you want to dive in with me.
If getting verified on EtherScan is important to you, then write your Solidity code wherever but compile it using Browser Solidity here: http://chriseth.github.io/browser-solidity/
Then use that bytecode to deploy. I have not tested it but the code it spits out for the sample token contract matches what EtherScan spits out. I assume that EtherScan is using that same browser-based compiler to check and verify contracts.
If you are using Mix IDE / Solidity, you can view the Solidity version by going (in the Mix IDE) to File/Mix/Help - > About.
If you are using solc / Solidity (command line interface) you can use the command
web3.eth.compile
which will then spit out something like:This will compile your code and give you information like compiler version, etc.
More Information
Optimization is a choice you can make. Via solc, you use the
--optimize
flag. You can read more about this magical optimization property here: How does the solidity optimizer work?. I think Mist is optimizing based on the fact that I had a 73% similarity when I chose "not optimized" on EtherScan and a 93% similarity when I chose optimized.Contract Testing:
I have created the exact contract https://www.ethereum.org/token#the-code with no change whatsoever to the code using Mist v 0.5.2.
The contract code that Etherscan.io received / Mist sent was:
You can see this on EtherScan, or you can get it in Ethereum Wallet by opening the console and running
TokenContract.eth.getCode('YOUR_ADDRESS_HERE_NO_0x_AT_BEGINNING');
Both Mist and EtherScan spit out the same code.I attempted to verify maybe 20 different versions, with and without optimization, using Browser Solidity and never once is that code as short or Etherscan.io has it, nor does it start with 0x.....
Here is an example of what Browser Solidity & EtherScan give me using 0.2.1-3ad5e821 w/ optimization:
So....it still doesn't match what Mist supposedly sent and EtherScan received.
While doing research, I found that EtherChain may have better luck with verification. I, however, still could not get anything above ~93% similarity (using 2.1.1, optimized).
Hope this helps someone.