31

What is the difference between the constant and immutable keywords in Solidity and how do I use them?

Shane Fontaine
  • 18,036
  • 20
  • 54
  • 82

3 Answers3

32

Both immutable and constant are keywords that can be used on state variables to restrict modifications to their state. The difference is that constant variables can never be changed after compilation, while immutable variables can be set within the constructor.

From the docs:

State variables can be declared as constant or immutable. In both cases, the variables cannot be modified after the contract has been constructed. For constant variables, the value has to be fixed at compile-time, while for immutable, it can still be assigned at construction time.

An example code snippet is as follows:

pragma solidity >0.6.4 <0.7.0;

contract C {
    uint constant X = 32**22 + 8;
    string constant TEXT = "abc";
    bytes32 constant MY_HASH = keccak256("abc");
    uint immutable decimals;
    uint immutable maxBalance;
    address immutable owner = msg.sender;

    constructor(uint _decimals, address _reference) public {
        decimals = _decimals;
        // Assignments to immutables can even access the environment.
        maxBalance = _reference.balance;
    }

    function isBalanceTooHigh(address _other) public view returns (bool) {
        return _other.balance > maxBalance;
    }
}

It is important to note that the compiler does not reserve a storage slot for these variables, and every occurrence is replaced by the respective value.

Shane Fontaine
  • 18,036
  • 20
  • 54
  • 82
  • How about the cost of gas for these 2 types of variable? – Ender Jul 28 '21 at 05:43
  • Found it: constant values can sometimes be cheaper than immutable values. – Ender Jul 28 '21 at 05:44
  • @Ender In what cases and how would constant values be cheaper than immutable? – xenon Sep 09 '21 at 17:46
  • 1
    to see the answer to @xenon's question, see the end of the answer here: https://ethereum.stackexchange.com/a/113885/82367, "Immutable variables are evaluated once at construction time and their value is copied to all the places in the code where they are accessed. For these values, 32 bytes are reserved. [...] Due to this, constant values can sometimes be cheaper than immutable values." – Kyle Baker Dec 16 '21 at 05:43
  • Why would constants have any gas fee at all if they're just code replacements? – Ricardo Pedroni Dec 26 '21 at 13:59
  • I feel like this is really dumb. Why not allow constructor to assign once to a constant instead of making a whole new keyword just for that? - like other languages do? – Qwerty Jan 22 '22 at 17:40
  • @Qwerty which other languages ? C# for one also has readonly and constant keywords. I think it makes sense. – ihor.eth Feb 03 '22 at 22:00
7

In both cases, the variables cannot be modified after the contract has been constructed.

a) For constant variables, the value has to be fixed at compile-time.

b) For immutable, value can be assigned at construction time. They cannot be read during construction time and can only be assigned once.

No storage slot is reserved for such variables and their occurrence is replaced by their value.

Compared to regular state variables, the gas costs of constant & immutable variables are much lower.

a) For a constant variable, the expression assigned to it is copied to all the places where it is accessed and also re-evaluated each time. This allows for local optimizations.

b) Immutable variables are evaluated once at construction time and their value is copied to all the places in the code where they are accessed. For these values, 32 bytes are reserved.

-> Due to this, constant values can sometimes be cheaper than immutable values.

Daniel Pham
  • 71
  • 1
  • 3
1

about this: "b) For immutable, value can be assigned at construction time. They cannot be read during construction time and can only be assigned once."

I can do this without problems. Compile and assignation works:

    uint public immutable immutableDecimal; 
    uint public enteroSinSigno;
    constructor(uint _decimalinmmutable) {
            immutableDecimal= _decimalinmmutable;
            enteroSinSigno = immutableDecimal;
    }
  • In the code you have mixed decimalImmutable with immutableDecimal. – Ismael May 05 '22 at 02:10
  • Right, what an oversight. I have corrected it. As I indicated I can read the value assigned in the constructor and use it to give value to another variable without problems. – Fernando López May 06 '22 at 09:24
  • @Ismael can read the immutable variables during creation time in v0.8.8 and above only. You can check here. – Daniel Pham Nov 17 '22 at 10:40
  • @DanielPham If you check the answer history there was an error with the variables names. It wasn't related to reading during creation. – Ismael Nov 18 '22 at 04:28