背景
使用 upgrades.erc1967.getImplementationAddress 来获取通过 upgrades.deployProxy 部署的合约的逻辑合约地址(implementation address)
测试部署脚本
const [deployer] = await ethers.getSigners();
console.log("Deployer:", await deployer.getAddress())
const commonBridgeFactory = await ethers.getContractFactory("CommonBridge", deployer);
let commonBridgeProxyContract;
if (deployOutput.commonBridgeProxyContract === undefined || deployOutput.commonBridgeProxyContract === '') {
commonBridgeProxyContract = await upgrades.deployProxy(
commonBridgeFactory,
[
process.env.DOMAIN_ID,
process.env.SUPER_ADMIN_ADDRESS,
process.env.BRIDGE_FEE_ADDRESS
],
{
constructorArgs: [],
unsafeAllow: ['constructor', 'state-variable-immutable'],
});
console.log('tx hash:', commonBridgeProxyContract.deploymentTransaction().hash);
} else {
commonBridgeProxyContract = commonBridgeFactory.attach(deployOutput.commonBridgeProxyContract);
}
console.log('commonBridgeProxyContract deployed to:', commonBridgeProxyContract.target);
await sleep(6000);
const commonBridgeImpl = await upgrades.erc1967.getImplementationAddress(commonBridgeProxyContract.target);
console.log('commonBridgeProxyContract implementation deployed to:', commonBridgeImpl);
部署超时
Error: Timed out waiting for implementation contract deployment to address 0x5393... with transaction 0x9492...
解决:增加超时和轮询设置
...
commonBridgeProxyContract = await upgrades.deployProxy(
commonBridgeFactory,
[
process.env.DOMAIN_ID,
process.env.SUPER_ADMIN_ADDRESS,
process.env.BRIDGE_FEE_ADDRESS
],
{
constructorArgs: [],
unsafeAllow: ['constructor', 'state-variable-immutable'],
timeout: 300000, // 5分钟
pollingInterval: 5000, // 每5秒轮询一次
});
console.log('tx hash:', commonBridgeProxyContract.deploymentTransaction().hash);
...
不符合 ERC1967 标准
使用 upgrades.erc1967.getImplementationAddress 来获取通过 upgrades.deployProxy 部署的合约的逻辑合约地址(implementation address),结果报:部署地址不符合 ERC1967 标准的代理合约(Proxy)
Error: Contract at 0xffa5f716D890CFd4f9D709A40d6EB7Fb19fC43B4 doesn't look like an ERC 1967 proxy with a logic contract address
const implSlot = '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc';
const proxyAddress = '0xffa5f716D890CFd4f9D709A40d6EB7Fb19fC43B4';
const storage = await ethers.provider.getStorage(proxyAddress, implSlot);
console.log("Raw implementation slot:", storage);
const implAddress = '0x' + storage.slice(-40);
console.log("Implementation address:", implAddress);
const implAddress1 = await upgrades.erc1967.getImplementationAddress(proxyAddress);
console.log("Implementation address1:", implAddress1);
如果返回的 implStorage 是全零(0x000...),说明实现地址确实没有写进去,可能部署时失败或未初始化。
如果你用其他方式部署 Proxy(比如自己 new TransparentUpgradeableProxy,而不是用 upgrades.deployProxy()),OpenZeppelin 插件就不能保证你用了它支持的初始化逻辑。
解决: 是因为网络延迟原因,增加延迟时间
console.log('commonBridgeProxyContract deployed to:', commonBridgeProxyContract.target);
await sleep(20000); // 提高延迟间隔
const commonBridgeImpl = await upgrades.erc1967.getImplementationAddress(commonBridgeProxyContract.target);
console.log('commonBridgeProxyContract implementation deployed to:', commonBridgeImpl);
最终版本
const [deployer] = await ethers.getSigners();
console.log("Deployer:", await deployer.getAddress())
const commonBridgeFactory = await ethers.getContractFactory("CommonBridge", deployer);
let commonBridgeProxyContract;
if (deployOutput.commonBridgeProxyContract === undefined || deployOutput.commonBridgeProxyContract === '') {
commonBridgeProxyContract = await upgrades.deployProxy(
commonBridgeFactory,
[
process.env.DOMAIN_ID,
process.env.SUPER_ADMIN_ADDRESS,
process.env.BRIDGE_FEE_ADDRESS
],
{
constructorArgs: [],
unsafeAllow: ['constructor', 'state-variable-immutable'],
timeout: 300000,
pollingInterval: 5000,
});
console.log('tx hash:', commonBridgeProxyContract.deploymentTransaction().hash);
} else {
commonBridgeProxyContract = commonBridgeFactory.attach(deployOutput.commonBridgeProxyContract);
}
console.log('commonBridgeProxyContract deployed to:', commonBridgeProxyContract.target);
await sleep(20000);
const commonBridgeImpl = await upgrades.erc1967.getImplementationAddress(commonBridgeProxyContract.target);
console.log('commonBridgeProxyContract implementation deployed to:', commonBridgeImpl);



