Merge pull request #14304 from ethereum/relax-restrictions-on-immutable-initialization-outside-functions-and-modifiers

Relax restrictions on immutable initialization (outside of functions and modifiers)
This commit is contained in:
Kamil Śliwak
2023-07-17 16:38:57 +02:00
committed by GitHub
56 changed files with 207 additions and 419 deletions
+1 -1
View File
@@ -150,7 +150,7 @@ Modifiers
- ``view`` for functions: Disallows modification of state.
- ``payable`` for functions: Allows them to receive Ether together with a call.
- ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot.
- ``immutable`` for state variables: Allows exactly one assignment at construction time and is constant afterwards. Is stored in code.
- ``immutable`` for state variables: Allows assignment at construction time and is constant when deployed. Is stored in code.
- ``anonymous`` for events: Does not store event signature as topic.
- ``indexed`` for event parameters: Stores the parameter as topic.
- ``virtual`` for functions and modifiers: Allows the function's or modifier's
+30 -18
View File
@@ -30,19 +30,23 @@ Not all types for constants and immutables are implemented at this time. The onl
.. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.4;
pragma solidity ^0.8.21;
uint constant X = 32**22 + 8;
contract C {
string constant TEXT = "abc";
bytes32 constant MY_HASH = keccak256("abc");
uint immutable decimals;
uint immutable decimals = 18;
uint immutable maxBalance;
address immutable owner = msg.sender;
constructor(uint decimals_, address ref) {
decimals = decimals_;
if (decimals_ != 0)
// Immutables are only immutable when deployed.
// At construction time they can be assigned to any number of times.
decimals = decimals_;
// Assignments to immutables can even access the environment.
maxBalance = ref.balance;
}
@@ -74,10 +78,29 @@ Immutable
=========
Variables declared as ``immutable`` are a bit less restricted than those
declared as ``constant``: Immutable variables can be assigned an arbitrary
value in the constructor of the contract or at the point of their declaration.
They can be assigned only once and can, from that point on, be read even during
construction time.
declared as ``constant``: Immutable variables can be assigned a
value at construction time.
The value can be changed at any time before deployment and then it becomes permanent.
One additional restriction is that immutables can only be assigned to inside expressions for which
there is no possibility of being executed after creation.
This excludes all modifier definitions and functions other than constructors.
There are no restrictions on reading immutable variables.
The read is even allowed to happen before the variable is written to for the first time because variables in
Solidity always have a well-defined initial value.
For this reason it is also allowed to never explicitly assign a value to an immutable.
.. warning::
When accessing immutables at construction time, please keep the :ref:`initialization order
<state-variable-initialization-order>` in mind.
Even if you provide an explicit initializer, some expressions may end up being evaluated before
that initializer, especially when they are at a different level in inheritance hierarchy.
.. note::
Before Solidity 0.8.21 initialization of immutable variables was more restrictive.
Such variables had to be initialized exactly once at construction time and could not be read
before then.
The contract creation code generated by the compiler will modify the
contract's runtime code before it is returned by replacing all references
@@ -86,14 +109,3 @@ you are comparing the
runtime code generated by the compiler with the one actually stored in the
blockchain. The compiler outputs where these immutables are located in the deployed bytecode
in the ``immutableReferences`` field of the :ref:`compiler JSON standard output <compiler-api>`.
.. note::
Immutables that are assigned at their declaration are only considered
initialized once the constructor of the contract is executing.
This means you cannot initialize immutables inline with a value
that depends on another immutable. You can do this, however,
inside the constructor of the contract.
This is a safeguard against different interpretations about the order
of state variable initialization and constructor execution, especially
with regards to inheritance.
+2
View File
@@ -30,6 +30,8 @@ Semantic Only Changes
This section lists the changes that are semantic-only, thus potentially
hiding new and different behavior in existing code.
.. _state-variable-initialization-order:
- The order of state variable initialization has changed in case of inheritance.
The order used to be: