Summary
Some contracts are already deployed, and their current version will be upgraded following the deployment of contracts in this audit. However, the issue arises because the newly deployed contract will not be initialized due to the incorrect modifier version used.
Vulnerability Details
The following contracts will not be upgraded, or their initialize
function will revert:
OperatorVCS
: This contract uses an incorrect initialize
version.
OperatorVault
: This contract uses an incorrect initialize
version.
CommunityVCS
: This contract employs the initialize
function.
CommunityVault
: This contract employs the initialize
function.
A simple code snippet to demonstrate this issue:
Setup a simple foundry project and install openzeppelin contracts than add following code :
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyContractV1 is Initializable, UUPSUpgradeable {
uint256 public value;
function initialize() public initializer {
value = 42;
}
function _authorizeUpgrade(address newImplementation) internal override {}
function setValue(uint256 newValue) public {
value = newValue;
}
}
contract MyContractV2 is Initializable, UUPSUpgradeable {
uint256 public value;
uint256 public newValue;
function increment() public {
value += 1;
}
function reinitializeV2() public reinitializer(1) {
newValue = 100;
}
function _authorizeUpgrade(address newImplementation) internal override {}
}
Add following test code inside test dir :
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import {MyContractV1 , MyContractV2} from "../src/MyContract.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract UUPSTest is Test {
MyContractV1 public myContractV1;
MyContractV2 public myContractV2;
ERC1967Proxy public proxy;
MyContractV1 public proxyAsV1;
MyContractV2 public proxyAsV2;
event UpdateStrategyRewards(
int rewardsAmount
);
function setUp() public {
myContractV1 = new MyContractV1();
bytes memory data = abi.encodeWithSignature("initialize()");
proxy = new ERC1967Proxy(address(myContractV1), data);
proxyAsV1 = MyContractV1(address(proxy));
assertEq(proxyAsV1.value(), 42);
}
function testUpgradeToV2WithReinitializer() public {
myContractV2 = new MyContractV2();
vm.prank(address(this));
proxyAsV1.upgradeTo(address(myContractV2));
proxyAsV2 = MyContractV2(address(proxy));
assertEq(proxyAsV2.value(), 42);
proxyAsV2.reinitializeV2();
assertEq(proxyAsV2.newValue(), 100);
proxyAsV2.increment();
assertEq(proxyAsV2.value(), 43);
}
function testEvent() external {
int256 a = -1234;
emit UpdateStrategyRewards(a);
}
}
Run with command : forge test --mt testUpgradeToV2WithReinitializer
.
Impact
These contracts can not be deployed and will result in a revert.
Tools Used
Manual review
Recommendations
Check the versions of all already deployed contracts and ensure that the correct version is used for new deployments
For example, for OperatorVCS
, the current version is 3, and we need to use version 4 here.