Solidity07 常数 constant和immutable

这一个文档,我们介绍Solidity中和常量相关的两个关键字,constant(常量)和immutable(不变量)。状态变量声明这两个关键字之后,不能在初始化后更改数值。这样做的好处是提升合约的安全性并节省gas

另外,只有数值变量可以声明constantimmutablestringbytes可以声明为constant,但不能为immutable

一、常量的定义

在智能合约中,如果一个状态变量的值恒定不变,就可以使用关键字 constant 或者 immutable 进行修饰,把它定义为常量。

复制代码
string constant SYMBOL = "WETH";
uint256 immutable TOTAL_SUPPLY = 1000;

常量的命名规则与变量相同,但通常使用大写字母表示,单词之间用下划线 "_" 连接,这样与变量更容易区分。这不是强制性的规定,而是大家约定俗成的编程规范。

状态变量一旦声明为 constantimmutable 后,就不能更改它的值了。

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ConstType { 
  string constant SYMBOL = "WETH"; // 定义常量 SYMBOL
 
  function getSymbol() public view returns(string memory) {
    return SYMBOL; // 可以读取常量 SYMBOL 的值
  }
  
  function setSymbol(string memory symbol) public {
    SYMBOL = symbol; // 编译时报错,不能修改常量 SYMBOL 的值
  }
}

我们将以上合约代码复制到 Remix,编译时就会报错,错误信息为:不能给一个常量重新赋值。

二、constant 和 immutable 的区别

constantimmutable 虽然都能限制对状态变量的修改,但两者还是有区别的,表现在两个方面:

2.1 初始化时机

constant 关键字修饰的状态变量,必须在声明时就立即显式赋值,然后就不再允许修改了。

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ConstType {
    uint8  public constant DECIMALS = 18; // 声明时赋值
}

immutable 关键字修饰的状态变量,既可以在声明时显式赋值,还可以在合约部署时赋值,也就是在合约的构造函数 constructor 中赋值。但是,一旦赋值后就不能再修改了。所以,immutableconstant 多了一个设置初值的机会,但是它花费的 gas 费要高一点。

比如,在 ERC20 代币合约中,通常将铸造总量 totalSupply 定义为 immutable,这样可以在合约部署时,由部署者按照实际需求填入数量,不用再去修改代码,从而提高了合约的通用性和灵活性。

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ConstType {
    uint8  public immutable DECIMALS = 18; // 声明时赋值
    uint256 public immutable TOTAL_SUPPLY;

     constructor() {
        TOTAL_SUPPLY = 1000; // 合约部署时赋值
    }
}

2.2 适用的数据类型

constant 可以修饰任何数据类型。

immutable 只能修饰值类型,比如:int、uint、bool、address 等,不能修饰 string、bytes 等引用类型。

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ConstType {
    uint256 constant TOTAL_SUPPLY = 100; // 正确
    uint256 immutable TOTAL_SUPPLY_I = 100; // 正确
    string constant SYMBOL = "WETH"; // 正确
    string immutable SYMBOL_I = "WETH"; // 错误
}

三、使用常量的好处

  1. 代码可读性

通过使用常量,可以为代码中使用的特定数值或字符串提供有意义的名称,增加代码的可读性,使代码更易于理解和维护。

  1. 代码重用

通过将常量定义为可复用的值,避免了在代码中重复输入。如果需要更改常量的值,只需修改它的定义,而不必在整个代码中寻找和替换多个出现的具体值。

  1. 预防错误

常量的值在编译时就被确定,并且在运行时不可修改。这可以帮助预防意外的值更改和错误的赋值操作,减少人为错误和意外行为。

  1. 节省 Gas

使用常量比变量更节省 gas 成本,这也是非常重要的一点。常量的值在编译时就已知,且不可改变,编译器会将其值直接嵌入到合约代码中,避免了在运行时进行存储和访问的开销。

四、代码示例

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract Constant {
    // constant变量必须在声明的时候初始化,之后不能改变
    uint256 public constant CONSTANT_NUM = 10;
    string public constant CONSTANT_STRING = "0xAA";
    bytes public constant CONSTANT_BYTES = "LJ";
    address public constant CONSTANT_ADDRESS = 0x0000000000000000000000000000000000000000;

    // immutable变量可以在constructor里初始化,之后不能改变
    uint256 public immutable IMMUTABLE_NUM = 9999999999;
    address public immutable IMMUTABLE_ADDRESS;
    uint256 public immutable IMMUTABLE_BLOCK;
    uint256 public immutable IMMUTABLE_TEST;

    // 利用constructor初始化immutable变量,因此可以利用
    constructor(){
        IMMUTABLE_ADDRESS = address(this);
        IMMUTABLE_NUM = 1118;
        IMMUTABLE_TEST = test();
    }

    function test() public pure returns(uint256){
        uint256 what = 9;
        return(what);
    }
}
  • 部署好合约之后,通过remix上的getter函数,能获取到constantimmutable变量初始化好的值。
  • constant变量初始化之后,尝试改变它的值,会编译不通过并抛出TypeError: Cannot assign to a constant variable.的错误。

  • immutable变量初始化之后,尝试改变它的值,会编译不通过并抛出TypeError: Immutable state variable already initialized.的错误。

这一章,我们介绍了Solidity中两个关键字,constant(常量)和immutable(不变量),让不应该变的变量保持不变。这样的做法能在节省gas的同时提升合约的安全性。

相关推荐
MicroTech202532 分钟前
隐私计算与区块链融合:微算法科技(NASDAQ MLGO)构建新一代区块链网络的创新实践
网络·科技·区块链
Sui_Network34 分钟前
社交游戏 Super-B 登陆 Epic 游戏商店抢先体验
人工智能·游戏·rpc·区块链·量子计算
友莘居士9 小时前
Hyperledger Fabric与 FISCO BCOS深度对比
区块链·fabric·fisco
公链开发10 小时前
区块链软件开发专家:达普韦伯的技术哲学与实战体系
区块链
Moonbeam Community13 小时前
走出围墙花园:Polkadot 2.0 如何在多链内卷中重整旗鼓
web3·区块链·solidity·polkadot
小明的小名叫小明17 小时前
Solidity入门(9)-合约间调用
区块链
千匠网络21 小时前
千匠网络农贸大宗电商系统:技术解决方案与行业实践深度解析
区块链·一站式商业云平台服务提供商·农贸大宗电商系统·农贸电商·大宗电商系统
村口曹大爷21 小时前
2025 区块链三国志:ETH 的内功、SOL 的极速与 BSC 的降维打击
web3·区块链
Sui_Network21 小时前
Mysten Labs 与不丹王国政府的创新与技术部携手探索离线区块链
大数据·人工智能·web3·去中心化·区块链