Secureum Book
  • 🛡️Secureum Bootcamp
    • 🛡️Secureum Bootcamp
    • 🙌Participate
    • 📜History
  • 📚LEARN
    • Introduction
      • 🔷1. Ethereum Basics
        • 1.1 Ethereum: Concept, Infrastructure & Purpose
        • 1.2 Properties of the Ethereum Infrastructure
        • 1.3 Ethereum vs. Bitcoin
        • 1.4 Ethereum Core Components
        • 1.5 Gas Metering: Solving the Halting Problem
        • 1.6 web2 vs. web3: The Paradigm Shift
        • 1.7 Decentralization
        • 1.8 Cryptography, Digital Signature & Keys
        • 1.9 Ethereum State & Account Types
        • 1.10 Transactions: Properties & Components
        • 1.11 Contract Creation
        • 1.12 Transactions, Messages & Blockchain
        • 1.13 EVM (Ethereum Virtual Machine) in Depth
        • 1.14 Transaction Reverts & Data
        • 1.15 Block Explorer
        • 1.16 Mainnet & Testnets
        • 1.17 ERCs & EIPs
        • 1.18 Legal Aspects in web3: Pseudonymity & DAOs
        • 1.19 Security in web3
        • 1.20 web2 Timescales vs. web3 Timescales
        • 1.21 Test-in-Prod. SSLDC vs. Audits
        • Summary: 101 Keypoints
      • 🌀2. Solidity
        • 2.1 Solidity: Influence, Features & Layout
        • 2.2 SPDX & Pragmas
        • 2.3 Imports
        • 2.4 Comments & NatSpec
        • 2.5 Smart Contracts
        • 2.6 State Variables: Definition, Visibility & Mutability
        • 2.7 Data Location
        • 2.8 Functions
        • 2.9 Events
        • 2.10 Solidity Typing
        • 2.11 Solidity Variables
        • 2.12 Address Type
        • 2.13 Conversions
        • 2.14 Keywords & Shorthand Operators
        • 2.15 Solidity Units
        • 2.16 Block & Transaction Properties
        • 2.17 ABI Encoding & Decoding
        • 2.18 Error Handling
        • 2.19 Mathematical & Cryptographic Functions
        • 2.20 Control Structures
        • 2.21 Style & Conventions
        • 2.22 Inheritance
        • 2.23 EVM Storage
        • 2.24 EVM Memory
        • 2.25 Inline Assembly
        • 2.26 Solidity Version Changes
        • 2.27 Security Checks
        • 2.28 OpenZeppelin Libraries
        • 2.29 DAppSys Libraries
        • 2.30 Important Protocols
        • Summary: 201 Keypoints
      • 🔏3. Security Pitfalls & Best Practices
        • 3.1 Solidity Versions
        • 3.2 Access Control
        • 3.3 Modifiers
        • 3.4 Constructor
        • 3.5 Delegatecall
        • 3.6 Reentrancy
        • 3.7 Private Data
        • 3.8 PRNG & Time
        • 3.9 Math & Logic
        • 3.10 Transaction Order Dependence
        • 3.11 ecrecover
        • 3.12 Unexpected Returns
        • 3.13 Ether Accounting
        • 3.14 Transaction Checks
        • 3.15 Delete Mappings
        • 3.16 State Modification
        • 3.17 Shadowing & Pre-declaration
        • 3.18 Gas & Costs
        • 3.19 Events
        • 3.20 Unary Expressions
        • 3.21 Addresses
        • 3.22 Assertions
        • 3.23 Keywords
        • 3.24 Visibility
        • 3.25 Inheritance
        • 3.26 Reference Parameters
        • 3.27 Arbitrary Jumps
        • 3.28 Hash Collisions & Byte Level Issues
        • 3.29 Unicode RTLO
        • 3.30 Variables
        • 3.31 Pointers
        • 3.32 Out-of-range Enum
        • 3.33 Dead Code & Redundant Statements
        • 3.34 Compiler Bugs
        • 3.35 Proxy Pitfalls
        • 3.36 Token Pitfalls
        • 3.37 Special Token Pitfalls
        • 3.38 Guarded Launch Pitfalls
        • 3.39 System Pitfalls
        • 3.40 Access Control Pitfalls
        • 3.41 Testing, Unused & Redundand Code
        • 3.42 Handling Ether
        • 3.43 Application Logic Pitfalls
        • 3.44 Saltzer & Schroeder's Design Principles
        • Summary: 201 Keypoints
      • 🗜️4. Audit Techniques & Tools
        • 4.1 Audit
        • 4.2 Analysis Techniques
        • 4.3 Specification, Documentation & Testing
        • 4.4 False Positives & Negatives
        • 4.5 Security Tools
        • 4.6 Audit Process
        • Summary: 101 Keypoints
      • ☝️5. Audit Findings
        • 5.1 Criticals
        • 5.2 Highs
        • 5.3 Mediums
        • 5.4 Lows
        • 5.5 Informationals
        • Summary: 201 Keypoints
  • 🌱CARE
    • CARE
      • CARE Reports
  • 🚩CTFs
    • A-MAZE-X CTFs
      • Secureum A-MAZE-X
      • Secureum A-MAZE-X Stanford
      • Secureum A-MAZE-X Maison de la Chimie Paris
Powered by GitBook
On this page
  • solc 0.6.0
  • Breaking Changes
  • Explicitness
  • Changes
  • New Features
  • solc 0.7.0
  • Breaking Changes
  • Changes
  • Removed
  • solc 0.8.0
  • Breaking Changes
  • Restrictions
  1. LEARN
  2. Introduction
  3. 2. Solidity

2.26 Solidity Version Changes

Every new Solidity version introduces bug fixes and sometimes breaking changes. Remember that breaking versions are versions that are not backwards compatible, or in other words they've introduced significant changes to the syntax, to the underlying semantics, that are not compatible with the previous changes.

These breaking versions increment the number that you see in the middle of the version, so for a Solidity version x.y.z, the next breaking version would be x.(y + 1).z.

In this section we are going to revise recent Solidity versions and their most impactful changes.

solc 0.6.0

Breaking Changes

In Solidity 0.6.0 a breaking semantic feature that was introduced changed the behavior of the existing code without changing the syntax itself. It was specifically related to the exponentiation. The type of the result until this version was the smallest type that could hold both the type of the base and the type of the exponent. With this change the resulting type was always the type of the base.

Explicitness

Solidity 0.6.0 also introduced a set of explicitness requirements. Explicitness, as you can imagine, is good for security because it reduces ambiguity and any vulnerabilities that result because of that ambiguity.

  1. In this case, keywords virtual and override were introduced for functions in base and derived classes. Functions and base classes can now only be overridden when they are marked with the virtual keyword, and their corresponding overriding functions need to use the override keyword.

  2. Array length is read-only: it's no longer possible with version 0.6.0 to resize storage arrays by assigning a new value to their length.

  3. An abstract keyword was introduced for what became abstract contracts or contracts where at least one function is not defined.

  4. Libraries have to implement all their functions, not only the internal ones, as of this version and there are various restrictions (explicitness restrictions) brought forward for the assembly variables.

  5. State variable shadowing being removed as this led to confusing results in ambiguity and has impacted the security of smart contracts.

Changes

There were many other syntactic and semantic changes brought forward by Solidity 0.6.0.

  • external function type conversions to address types are not allowed. Instead they have an address member that allows similar functionality.

  • Dynamic storage arrays have now their push(x) return nothing, while until then it returned the length of the array.

  • Until 0.6.0 there was a concept of unnamed functions. This version split the functionality implemented by such a functions into a fallback function and a separate receive function. As you know, there are differences between these two functions and specific use cases where one of them is applicable versus the other.

New Features

0.6.0 also introduced several new features:

  • try/catch blocks for exception handling.

  • struct and enum types can be declared at a file level with this version. Until then, it was only possible at contract level.

  • Array slices can be used for all data arrays.

  • NatSpec, as of this version supports multiple return parameters for developer documentation; it enforces the same naming checks as the param tag.

  • The inline assembly language YUL introduced a new statement called leave to help exit the current function.

  • Conversions from address type to address payable type are now possible via the payable(x) primitive, where x is of type address.

solc 0.7.0

Breaking Changes

The next breaking release was Solidity 0.7.0. With this version, exponentiation and shift of literals by non-literals will always use uint256 or int256 to perform the operation. Until this version the operation was performed using the type of the shift amount or the type of the exponent, which can be misleading, so this became very explicit.

This again is a breaking semantic change because the behavior of exponentiation and shifts changed underneath without any changes to the syntactic aspect.

Changes

This version also introduced several syntactic changes that could cause existing contracts to not compile anymore and therefore considered a breaking change. Examples of such changes are:

  • The syntax for specifying the Gas and Ether values applied during external calls.

  • The now keyword for time management within contracts was deprecated in favor of block.timestamp because now gave the perception that time could change within the context of a transaction whereas it is a property of the block, correctly indicated by block.timestamp.

  • The NatSpec aspect for variables was also changed to allow that for only public state variables and not for local or internal variables.

  • gwei was declared as a keyword and therefore can't be used for identifiers.

  • string literals can contain only printable ASCII characters. As of this version unicode string literals were also supported with the use of the unicode prefix.

  • The state mutability of functions during inheritance was also allowed to be restricted with this version, so functions with the default state mutability can be overridden by pure and view functions while the view functions can be overridden by pure functions.

There are also multiple changes introduced to the assembly support within Solidity.

Removed

This version also removed some features that were considered as unused or unsafe and therefore beneficial for security.

  • Struct or arrays that contained mappings were allowed to be used only in storage and not in memory, the reason for this was that mapping members within such structural arrays in memory were silently skipped. This as you can imagine would be error prone.

  • The visibility of constructors, either public or external is not needed anymore.

  • The virtual keyword is disallowed for library functions, because libraries can never be inherited from and therefore the library functions should not need to be virtual.

  • Multiple events with the same name and parameter types in an inheritance hierarchy are disallowed, again to reduce confusion.

  • The directive using A for B with respect to library functions and types affects only the contract it is specified in as of this version. Previously this was inherited, now it has to be repeated in all the derived contracts that require this feature.

  • Shifts by sign types are disallowed as of this version. Until now shift by negative amounts were allowed, but they caused a revert runtime.

  • The Ether denominations of fini and szabo were considered as rarely used and therefore were removed as of this version.

  • The keyword var was also removed because this would until now pass, but result in a type error as of this version.

solc 0.8.0

Breaking Changes

Solidity 0.8.0 is the latest of the breaking versions of Solidity. This version introduced several breaking changes:

  • The biggest perhaps is the introduction of default checked arithmetic. This is the overflow and underflow arithmetic checks that are so commonly used in Solidity contracts to prevent the wrapping behavior that results in overflows and has resulted in several security vulnerabilities.\

    Until this version, the best practice was to rely on the OpenZeppelin SafeMath libraries or their equivalents to make sure that there are runtime checks for overflows and underflows. These never result in vulnerabilities. This is so commonly used that Solidity 0.8.0 introduced the concept of checked arithmetic by default, so all the arithmetic that happens with increment, decrements, multiplication and division is all checked by default.\

    This might come at a slight increase of Gas Cost, but it also increases the default security level significantly and it also improves the readability of code because now one doesn't have to use or see the use of calls to the SafeMath libraries in the form of .add(), .sub() and, so on...\

    And as an escape hatch where the developer knows for sure that certain arithmetic is safe from such underflows and overflows, Solidity provides the unchecked primitive that is allowed to be used on blocks of arithmetic expressions where this default underflow and overflow checks are not done by the Solidity compiler.\

  • ABI coder version v2 is activated by default. As of this version, it doesn't have to be explicitly specified but if the developer wants to fall back on the older v1 version that has to be specified.

  • Exponentiation is right associative as opposed to being left associative that was the case. This is the common way to parse exponentiation operator in other languages, so this was fixed.

  • As of this version the use of the REVERT opcode versus the use of the INVALID opcode for failing asserts and internal checks was removed. Now both use the REVERT opcode and static analysis tools are allowed to distinguish these two differing situations by noticing the use of the panic error in the case of failing asserts and internal checks.\

    When storage byte arrays are accessed where the length is encoded incorrectly a panic is raised that's another change introduced.

  • The byte type which used to be an alias of bytes1 has been removed as of this version.

Restrictions

Solidity 0.8.0 also introduced several restrictions:

  • Explicit conversions of multiple types are disallowed. Remember that explicit conversions are where the user forces conversions between certain types without the compiler necessarily thinking those are safe from a type safety perspective, so these explicit conversions being disallowed may be considered as a good thing from a security perspective.

  • Address literals now have the type address instead of address payable, these have to be explicitly converted to address payable.

  • If required, the function call options for specifying the Gas and Ether value passed can only be provided once and not multiple times.

  • The global functions log0, log1 all the way to log4 that may be used for specifying events or logs have been removed because they were low level functions that were considered as largely unused by Solidity contracts and, if a developer wants to use them, they need to resort to inline assembly.

  • enum definitions now can't contain more than 256 members. This makes it safer because the underlying type is always uint8, so 8 bits that allows only 256 members to be represented by that type.

  • Declarations with name this, super and _ are disallowed.

  • Transaction origin (tx.origin) and message sender (msg.sender) global variables now have the type address instead of address payable, and again require an explicit conversion where address payable is needed.

  • The mutability of chainId is now considered view instead of pure.

All these different types of restrictions were introduced in this version that have an impact on security.

Previous2.25 Inline AssemblyNext2.27 Security Checks

Last updated 1 year ago

📚
🌀