doesn't look like an ERC 1967 proxy with a logic contract addres

Ethereum-新手教程 2025-07-17

背景

使用 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);

楼主残忍的关闭了评论