Constant 和 Immutable 状态变量

状态变量声明为 constant 或者 immutable ,在这两种情况下,合约一旦部署之后,变量将不在修改。

对于 constant 变量, 他的值在编译器确定,而对于 immutable, 它的值在部署时确定。

编译器不会为这些变量预留存储位,它们的每次出现都会被替换为相应的常量表达式(它可能被优化器计算为实际的某个值)。

不是所有类型的状态变量都支持用 constant 或 immutable 来修饰,当前仅支持 字符串 (仅常量) 和 值类型.

// SPDX-License-Identifier: GPL-3.0
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;
    }
}

Constant

如果状态变量声明为 constant。在这种情况下,只能使用那些在编译时有确定值的表达式来给它们赋值。 任何通过访问 storage,区块链数据(例如 now, address(this).balance 或者 block.number)或执行数据( msg.valuegasleft() ) 或对外部合约的调用来给它们赋值都是不允许的。

允许可能对内存分配产生副作用(side-effect)的表达式,但那些可能对其他内存对象产生副作用的表达式则不允许。

内建(built-in)函数 keccak256sha256ripemd160ecrecoveraddmodmulmod 是允许的(即使他们确实会调用外部合约, keccak256 除外)。

允许内存分配器的副作用的原因是它可以构造复杂的对象,例如: 查找表(lookup-table)。 此功能尚不完全可用。

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 cannot be read during construction time and can only be assigned once.

The contract creation code generated by the compiler will modify the contract’s runtime code before it is returned by replacing all references to immutables by the values assigned to the them. This is important if you are comparing the runtime code generated by the compiler with the one actually stored in the blockchain.