Latest release of Solidity compiler Improvements and highlights of new features

New and Improved Solidity Compiler Highlights of Latest Updates and Features

Compiled: Denglian Translation Plan; Source: soliditylang.org

The latest version v0.8.22 of the Solidity compiler has been released. The compiler version 0.8.22 includes a series of language and compiler improvements, such as file-level event definitions, unchecked loop increment optimization, support for importing EVM assembly JSON, and so on.

Important Note

This release deprecates support for EVM versions lower than Constantinople. These older versions have become increasingly difficult to maintain. They are already outdated on the Ethereum mainnet and test networks, and we suspect they are no longer relevant for other networks as well. Complex code paths and solutions slow down the development and testing of features for newer versions, so we hope to stop supporting them in future compiler versions.

New Feature Highlights

Unchecked Loop Increment

Using unchecked arithmetic operations when incrementing loop counters is a common practice for gas optimization. Let’s illustrate this with an example of a loop and a counter variable i:

for (uint i = 0; i < array.length; ++i) { acc += array[i]; // i is not modified by the loop body}

In many cases (detailed conditions below), the comparison operation ensures that i will never reach the maximum value of its type. Therefore, it is safe to assume that the loop will stop before reaching the maximum value. In this case, performing a safe check on the counter would be redundant and a waste of gas. This encourages users to use the lengthy unchecked pattern, wrapping the counter increment in an unchecked arithmetic block inside the loop body:

for (uint i = 0; i < array.length;) { acc += array[i]; unchecked { i++; } // i gets incremented without overflow checks -- less gas used}

Solidity 0.8.22 introduces an overflow check optimization that automatically generates the unchecked arithmetic increment for loop counters. This new optimization eliminates the need for using the lengthy unchecked increment pattern in the loop body like the previous example.

In contrast, the new optimization allows users to return to the original, more readable code without sacrificing gas efficiency.

The new optimization avoids overflow checks under the following precise conditions:

  • The loop condition is a comparison of the form i < ..., where i is a local variable (now referred to as “loop counter”).

  • This comparison must be performed on the same type as the loop counter, i.e., the type on the right must be implicitly convertible to the type of the loop counter, so that the loop counter is not implicitly extended before the comparison.

  • The loop counter must be a local variable of a built-in integer type.

  • The loop expression must be the prefix or postfix increment of the loop counter, i.e., either i++ or ++i.

  • The loop counter must not be modified in the loop condition or loop body.

To clarify the second condition, consider the following code snippet:

for (uint8 i = 0; i < uint16(1000); ++i) {    // loop body}

In this case, i is converted to uint16 before the comparison, and the condition will never be false, so the increment overflow check cannot be removed.

Also note that < is the only comparison operator that triggers this optimization. Operators <= and others are deliberately excluded. Additionally, the operator must be built-in – user-defined < does not qualify.

This optimization is direct and always beneficial, so it is enabled even if the rest of the optimizer is disabled using the settings.optimizer.enabled general setting. It can be explicitly disabled by setting settings.optimizer.details.simpleCounterForLoopUncheckedIncrement to false in the standard JSON input. It cannot be disabled via the command-line interface.

Adjust Yul optimizer to regenerate zero literals

This new version builds on the support of the PUSH0 opcode introduced in version 0.8.20, by extending the Rematerialiser[8] optimization step to always regenerate zero literals instead of storing them as variable references, enabling the use of PUSH0 instead of DUP to reduce gas costs. To ensure effective execution of this operation, the Rematerialiser and UnusedPruner[9] steps have been added to the default optimization sequence of the Yul optimizer.

Add support for importing EVM assembly JSON (experimental)

This new version adds experimental support for importing EVM assembly, providing possibilities for external tools to perform super-optimizations before bytecode generation. The primary purpose of this feature is to define a serialization format for low-level EVM assembly, allowing the generated assembly by the compiler to be exported, modified, and reimported, thus restoring normal compilation processes.

Important note: This is an experimental feature and is currently not suitable for production environments. We are providing this feature in this version for you to try out and provide feedback.

Allow event definitions at the file level

Solidity 0.8.22 allows you to define events at the file level. Now, event definitions can be placed outside the scope of a contract. This provides another option for code organization without the need to artificially wrap events in libraries.

In addition, this version also fixes an issue that caused NatSpec generation to fail when emitting events defined in external contracts or interfaces. In the previous version (0.8.21), the Solidity compiler added support for limited access to events defined in contracts and interfaces that are not inherited by the current contract, but this bug prevented the full use of that feature.

With this bug fix and the ability to define events at the file level, the latest version of Solidity allows users to compile the following example without any errors:

interface I {    event ForeignEvent();}contract C {    event ForeignEvent();}event E();contract D {    function f() public {        // Emitting a foreign event would trigger an internal error on 0.8.21        emit I.ForeignEvent();        emit C.ForeignEvent();        // Emitting a file-level event. New feature.        emit E();    }}

Complete Change Log

Language Features

  • Allow events to be defined at the file level.

Compiler Features

  • Code generator: Remove redundant overflow checks for certain for loops when the counter variable will not overflow.

  • Command-line interface: Add --no-import-callback option to prevent the compiler from loading source files that are not explicitly given in the CLI or standard JSON input.

  • Command-line interface: Add experimental --import-asm-json option to import EVM assembly in the format used with --asm-json.

  • Command-line interface: Use appropriate severity and coloring for error messages generated outside of the compilation pipeline.

  • EVM: Deprecate support for “homestead”, “tangerineWhistle”, “spuriousDragon”, and “byzantium” versions of the EVM.

  • Parser (LianGuairser): Remove experimental error recovery mode (--error-recovery / settings.parserErrorRecovery).

  • SMTChecker: Support user-defined operators.

  • Yul optimizer: Prioritize using zero literals instead of storing zero values in variables if support for PUSH0 exists.

  • Yul optimizer: Run Rematerializer and UnusedPruner steps at the end of the default cleanup sequence.

Bug Fixes

  • Code generator: Fix an issue where the result of code generation via the via-IR code generator would depend on files discovered in the import callback. In some cases, different AST ID assignments would change the order of functions in the internal schedule, resulting in bytecodes that were seemingly different but semantically equivalent.

  • NatSpec: Fix an internal error when requesting docstrings or devdoc for a contract that emits events defined in external contracts or interfaces.

  • SMTChecker: Fix encoding error causing loops to be unrolled after completion.

  • SMTChecker: Fix inconsistency in constant condition check when while or for loops are unrolled before the condition check.

  • Yul optimizer: Fix an issue where decisions on variable replacement were influenced by Yul variable names generated by the compiler during CSE, resulting in bytecodes that were different but equivalent in some cases.

We will continue to update Blocking; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Blockchain

FTX owns 38 properties in the Bahamas worth over 200 million US dollars.

The company stated that prior to filing for bankruptcy last year, it had paid out billions of dollars to executives, ...

Blockchain

Insurance giant Marsh has customized a full insurance plan for encrypted custodians, can cryptocurrency traders “sit back and relax”?

According to Coindesk's September 24 report, Marsh & McLennan, the world's largest insurance brokerage ...

Blockchain

Center absence: history, current status and prospects of atomic exchange and decentralized trading platforms

On July 30th, Liquid Network officially announced that Tether (USDt) has settled on the Liquid side chain, which mean...

Blockchain

Hong Kong Cryptocurrency New Policy's One-Year Anniversary A Year of Major Leaps and Key Milestone Review

Over the past year, Hong Kong has made great progress and shown strategic development in virtual asset policies. Sinc...

Market

Crypto Firms on the Move: Wallets Shaking and Bacon at Lighting Speed!

FTX and Alameda sent $10 million worth of popular tokens (LINK, MKR, COMP, ETH, and AAVE) to a wallet address, which ...

Blockchain

Exchange 5 hotspot tracking: The relationship between platform currency and IEO is like stocks and futures

On April 26th, an online conversation on the theme of “Exchange Hotspot Tracking” was held on TokenClub...