-
Notifications
You must be signed in to change notification settings - Fork 41
Open
Description
Description of the issue
I have the following two contracts: MyContractV1
and MyContractV2
as shown below.
When I run the Upgrades
plugin from the "openzeppelin-foundry-upgrades/LegacyUpgrades.sol"
library, the plugin warns that the new implementation MyContractV2
is unsafe because it contains a constructor
. However, this seems incorrect as this new implementation simply contains a constructor
to prevent the implementation from being initialized (the standard pattern with proxy + logic contracts).
Is this a false positive? Or is there something I am missing here? If I add in the Option
the options.unsafeAllow = "constructor";
, the error goes away.

Configurations
- using
@openzeppelin/contracts
v4.9.6 - using
openzeppelin-foundry-upgrades
v0.4.0
Examples contracts to reproduce the issue
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
import {
OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract MyContractV1 is OwnableUpgradeable {
uint256 public value;
constructor() {
_disableInitializers();
}
function initialize() public initializer {
__Ownable_init();
}
function setValue(uint256 _value) public onlyOwner {
value = _value;
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
import {
OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract MyContractV2 is OwnableUpgradeable {
uint256 public value;
string public name;
constructor() {
_disableInitializers();
}
function initialize() public initializer {
__Ownable_init();
}
function setValue(uint256 _value) public onlyOwner {
value = _value;
}
function setName(string memory _name) public onlyOwner {
name = _name;
}
}
Test to run to reproduce the issue
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {
Upgrades,
Options
} from "openzeppelin-foundry-upgrades/LegacyUpgrades.sol";
import {
TransparentUpgradeableProxy,
ITransparentUpgradeableProxy as IProxy
} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {MyContractV1} from "../src/MyContractV1.sol";
contract OZUpgradeExampleTest is Test {
address proxyAdmin;
MyContractV1 implementationV1;
IProxy proxy;
function setUp() public {
proxyAdmin = address(11);
implementationV1 = new MyContractV1();
bytes memory initializeCalldata = abi.encodeCall(
implementationV1.initialize,
()
);
proxy = IProxy(
address(
new TransparentUpgradeableProxy(
address(implementationV1),
proxyAdmin,
initializeCalldata
)
)
);
}
function test_deployNewImplementationAndUpgrade() public {
Options memory options;
options.referenceContract = "MyContractV1.sol";
// uncommenting this make the error goes away
// options.unsafeAllow = "constructor";
Upgrades.upgradeProxy(
address(proxy),
"MyContractV2.sol",
"",
options,
proxyAdmin
);
}
}
Command to run:
forge test --match-contract OZUpgradeExampleTest -vvv
JordyDutch
Metadata
Metadata
Assignees
Labels
No labels