Ethereum-Solidity 测验 Q14: 为什么在可升级合约中不能使用构造函数?
发布: (2026年1月6日 GMT+8 03:42)
2 min read
原文: Dev.to
Source: Dev.to
可升级合约中的构造函数行为
在 Solidity 中,放在构造函数内部或全局变量声明中的代码 不会 成为已部署合约的运行时字节码的一部分。这段代码仅在合约实例部署的那一刻执行一次。
当逻辑合约被代理(proxy)使用时,逻辑合约的构造函数根本不会在代理的存储上下文中执行。代理对构造函数所做的任何存储更改完全不知情。
解决方案:使用初始化函数
为了使合约具备可升级性,需要将构造函数逻辑移到普通的 初始化 函数中,并在代理链接到逻辑合约后调用该函数。初始化函数必须受到保护,确保只能调用一次——这与构造函数提供的一次性执行保证相同。
OpenZeppelin Upgrades 允许在部署代理时指定初始化函数的名称(以及其参数)。
使用 OpenZeppelin Initializable 的示例
// contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract MyContract is Initializable {
function initialize(
address arg1,
uint256 arg2,
bytes memory arg3
) public payable initializer {
// "constructor" code...
}
}
该合约继承自 Initializable,该基类提供了 initializer 修饰符,确保 initialize 函数只能执行一次。
摘自 OpenZeppelin 文档