使用OpenZeppelin deployProxy部署代理时代码优化器设置不生效
问题分析与解决方案
核心问题根源
OpenZeppelin升级套件(@openzeppelin/truffle-upgrades或@openzeppelin/hardhat-upgrades)默认使用预编译好的代理合约 artifacts(包括TransparentUpgradeableProxy和ProxyAdmin),这些合约在npm包发布时就已编译完成,且默认启用了优化器(runs:200)。你的本地编译器配置(关闭优化)只会影响自己编写的合约(比如Erc20Token),无法覆盖预编译代理合约的字节码设置。
手动修改node_modules里的build-info.json无效,因为插件实际读取的是预编译的字节码文件(如.bin),而非该配置文件,且npm包更新后会覆盖你的修改。
解决方案:自定义编译并部署代理合约
要让代理合约使用关闭优化的编译配置,需将代理合约源码复制到本地项目,用自己的编译器配置编译,再手动部署整套可升级合约体系:
步骤1:复制代理合约源码到本地
从node_modules中复制以下两个合约到你的项目contracts目录:
@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol@openzeppelin/contracts-upgradeable/proxy/transparent/TransparentUpgradeableProxy.sol
步骤2:保持编译器配置不变
确保你的truffle-config.js中优化器已关闭(你已完成这一步):
compilers: { solc: { version: "0.8.16", settings: { optimizer: { enabled: false, runs: 200 } } } }
步骤3:修改迁移脚本,手动部署所有合约
替换原有的deployProxy调用,改为手动部署逻辑合约、管理员合约和代理合约:
const Erc20Token = artifacts.require('Erc20Token'); const ProxyAdmin = artifacts.require('ProxyAdmin'); const TransparentUpgradeableProxy = artifacts.require('TransparentUpgradeableProxy'); module.exports = async function (deployer) { // 1. 部署ERC20逻辑合约 await deployer.deploy(Erc20Token); const erc20Impl = await Erc20Token.deployed(); // 2. 部署ProxyAdmin合约 await deployer.deploy(ProxyAdmin); const proxyAdmin = await ProxyAdmin.deployed(); // 3. 编码初始化函数调用数据(如果initialize有参数,需传入对应值) const initializeData = erc20Impl.contract.methods.initialize().encodeABI(); // 4. 部署透明升级代理 await deployer.deploy( TransparentUpgradeableProxy, erc20Impl.address, // 逻辑合约地址 proxyAdmin.address, // 管理员地址 initializeData // 初始化调用数据 ); const proxyInstance = await TransparentUpgradeableProxy.deployed(); // 可选:将代理地址转换为ERC20合约实例,方便后续调用 const erc20Token = await Erc20Token.at(proxyInstance.address); };
步骤4:重新编译部署
执行以下命令完成部署:
truffle console --network testnet truffle(testnet)> compile --all truffle(testnet)> migrate --reset
这样部署的TransparentUpgradeableProxy和ProxyAdmin都会使用你的本地编译配置(关闭优化器),测试网验证时会显示优化器状态为No。
内容的提问来源于stack exchange,提问作者Parshuram Thorat
相关产品推荐
相关产品推荐

