资讯动态

WTF-Solidity 极简入门:Solidity 状态变量只读化——constant 与 immutable 关键字完整指南

发布时间:2026/9/15 13:01:06 来源:尧图企业网站定制
WTF-Solidity 极简入门Solidity 状态变量只读化——constant 与 immutable 关键字完整指南【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidityconstant常量与immutable不变量是 Solidity 中用于限制状态变量修改的两大关键字。本文以 WTF-Solidity 仓库西语教程 Languages/es/09_Constante_es/readme.md 为主体结合仓库源码 Constant.sol 与主版本教程 09_Constant/readme.md系统讲解二者的声明语法、初始化时机、类型适用范围与编译期约束并给出可在 Remix 中逐条验证的实操步骤。学完本篇你将能在自己的合约中准确选用constant或immutable来固化不应变更的状态在提升合约安全性的同时节省gas。为什么需要 constant 与 immutable在 Solidity 中状态变量state variable默认是可写的任何函数都能修改它们的数值。但合约中总有一类一经确定就不该再变的数据——例如协议版本号、零地址、上限额度等。如果放任其随意被修改轻则造成逻辑混乱重则成为安全漏洞。constant与immutable正是为此而生的关键字状态变量一旦以这两个关键字声明其数值在编译/初始化完成后便无法再被修改。这种做法带来两方面的收益提升合约安全性将不应变化的数值在编译期焊死杜绝运行期被意外或恶意改写节省gasconstant与immutable变量的值在编译期被内联进字节码读取时不走常规的storage存储槽访问路径因此比普通可写状态变量的读取更省gas。类型适用范围不是所有类型都支持在动手声明之前需要先记住一个重要的类型限制数值类型value type变量既可以声明为constant也可以声明为immutablestring与bytes类型变量可以声明为constant但不能声明为immutable。这一规则在教程原文中明确给出也是 Solidity 语言层面的硬性约束。理解了适用范围下面分别看两种关键字的用法。constant 常量声明时必须初始化constant变量的规则最简单直接必须在声明的同时完成初始化初始化后任何时刻都不能再改变。一旦尝试修改编译将直接不通过。仓库源码 Constant.sol 给出了四个覆盖不同数据类型的示例// Una variable de tipo constante debe ser inicializada cuando es declarada, ya que después no se puede modificar // constant 变量必须在声明时初始化之后不能改变 uint256 public constant CONSTANT_NUM 10; string public constant CONSTANT_STRING 0xAA; bytes public constant CONSTANT_BYTES WTF; address public constant CONSTANT_ADDRESS 0x0000000000000000000000000000000000000000;对照源码可以看到四个变量在声明行内就完成了初始化uint256数值、string字符串、bytes字节串以及address零地址各占一种类型覆盖了最常见的常量使用场景。如果声明之后试图给constant变量重新赋值Solidity 编译器会抛出错误TypeError: Cannot assign to a constant variable.这正是教程在 Remix 中的验证结论constant变量一经初始化任何后续赋值都是非法的错误在编译阶段就会被拦截而非等到部署运行后才暴露。immutable 不变量声明时或构造函数中初始化immutable相比constant更加灵活它既可以在声明时初始化也可以在构造函数constructor中初始化。一旦初始化完成其数值同样不可再变。仓库源码 Constant.sol 中的示例同时用到了两种初始化方式// Las variables inmutables pueden ser inicializadas en el constructor y no se pueden modificar después // immutable 变量可以在构造函数中初始化之后不能改变 uint256 public immutable IMMUTABLE_NUM 9999999999; address public immutable IMMUTABLE_ADDRESS; uint256 public immutable IMMUTABLE_BLOCK; uint256 public immutable IMMUTABLE_TEST;其中IMMUTABLE_NUM在声明时就被初始化为9999999999而其余三个变量只在声明处留了空位等待构造函数赋值。用全局变量或自定义函数初始化immutable灵活性的另一体现是它可以使用 Solidity 的全局变量如address(this)、block.number甚至自定义函数来初始化。这使它能够捕获部署时刻的链上环境信息而这在编译期是无法预知的。源码 Constant.sol 的构造函数演示了三种初始化来源// Las variables inmutables son inicializadas en el constructor, por lo que se pueden usar en el resto del contrato // immutable 变量在构造函数中初始化之后可在合约其余部分使用 constructor(){ IMMUTABLE_ADDRESS address(this); IMMUTABLE_BLOCK block.number; IMMUTABLE_TEST test(); } function test() public pure returns(uint256){ uint256 what 9; return(what); }IMMUTABLE_ADDRESS address(this);把当前合约自身的地址固化下来IMMUTABLE_BLOCK block.number;记录合约部署时的区块号IMMUTABLE_TEST test();调用自定义的pure函数test()将返回值9写入变量。test()是一个pure函数不读取也不修改状态纯粹返回9因此可以安全地在构造函数中调用。这种用函数返回值初始化只读状态变量的模式在实际合约中常被用于将部署参数、时间戳等动态信息一次性地固化。重复初始化的后果如果immutable变量在声明处已初始化又在构造函数中再次赋值即重复初始化编译器同样会拦截TypeError: Immutable state variable already initialized.值得注意的是主版本中文教程 09_Constant/readme.md 还补充了两条进阶规则仓库内可验证若immutable变量既在声明时初始化、又在构造函数中初始化最终生效的是构造函数中初始化的值在Solidity v0.8.21 之后immutable变量不再要求显式初始化未显式初始化的变量会采用数值类型的初始值参见 08_InitialValue/readme.md 中关于变量初始值的讲解反之在更早版本中则需要显式初始化。这两条规则对判断最终读到什么值至关重要建议结合自己的编译器版本仔细核对。完整源码对照将上述片段组合起来就是本讲完整的示例合约西语版 Constant.sol主版本 09_Constant/Constant.sol// SPDX-License-Identifier: MIT pragma solidity ^0.8.34; contract Constant { // constant 变量必须在声明时初始化之后不能改变 uint256 public constant CONSTANT_NUM 10; string public constant CONSTANT_STRING 0xAA; bytes public constant CONSTANT_BYTES WTF; address public constant CONSTANT_ADDRESS 0x0000000000000000000000000000000000000000; // immutable 变量可以在构造函数中初始化之后不能改变 uint256 public immutable IMMUTABLE_NUM 9999999999; address public immutable IMMUTABLE_ADDRESS; uint256 public immutable IMMUTABLE_BLOCK; uint256 public immutable IMMUTABLE_TEST; // immutable 变量在构造函数中初始化因此可以在合约其余部分使用 constructor(){ IMMUTABLE_ADDRESS address(this); IMMUTABLE_BLOCK block.number; IMMUTABLE_TEST test(); } function test() public pure returns(uint256){ uint256 what 9; return(what); } }两个目录下的.sol文件内容一致均采用pragma solidity ^0.8.34编译指令。由于所有变量都以public声明Solidity 会自动为它们生成同名的getter函数方便在部署后直接读取。说明声明了public constant/public immutable的变量自动生成getter这也是在 Remix 中可以直接点按查看数值的原因。在 Remix 中验证实操三步走教程原文给出了完整的 Remix 验证流程下面逐条展开。打开 Remix新建合约文件并粘贴上面的完整代码选择^0.8.34版本编译部署即可复现。第一步部署后通过 getter 读取初始化值部署合约后Remix 的合约面板会自动列出CONSTANT_*与IMMUTABLE_*两组变量的getter按钮。点击后即可看到初始化完成后的数值constant变量显示声明时写入的字面量immutable变量显示构造函数中写入的值如当前合约地址、部署区块号与test()的返回值9。第二步尝试修改 constant 变量在合约中新增一个函数尝试给CONSTANT_NUM等变量重新赋值例如CONSTANT_NUM 777;随后点击编译。Remix 会在编译面板中抛出一连串红色错误核心信息为TypeError: Cannot assign to a constant variable.这印证了教程的结论constant变量初始化后不可赋值任何修改尝试都会被编译器直接拒绝。第三步尝试重复初始化 immutable 变量在构造函数中对一个已在声明处初始化过的immutable变量如IMMUTABLE_NUM再次赋值编译时同样会报错TypeError: Immutable state variable already initialized.注意该错误指向的是构造函数中重复赋值的那一行说明 Solidity 精确地定位到了非法操作的位置。总结本讲围绕 Solidity 中两个只读化关键字展开constant常量必须在声明时初始化之后永远不可修改适用于编译期即可确定且永不变化的字面量immutable不变量可在声明时或构造函数中初始化更为灵活适用于部署时刻才能确定、此后又不应改变的数据合约地址、区块号等类型约束数值类型两者皆可string/bytes只能用于constant收益让不该变的变量保持不变在提升合约安全性的同时节省gas。在编写合约时凡是确定性数据都应当优先考虑用constant或immutable固化这既是良好的编码习惯也是合约安全与成本优化的基本功。若需复习状态变量的初始值规则可继续阅读仓库中的 08_InitialValue/readme.md。【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价