Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: low
Valid

OperatorVCS.sol cannot be initialized due to incorrect version being in use

Summary

The reinitializer version set in OperatorVCS.sol corresponds to its previous implementation which will cause the initialization of the new contract to fail.

Vulnerability Details

OperatorVCS.sol is an upgrade of the previous contract of the same name. Which is why its initialize uses the reinitializer modifier. However, the version set in the reinitializer is the same as the previous version.

For comaprison, here's our current implementation

function initialize(
address _token,
address _stakingPool,
address _stakeController,
address _vaultImplementation,
Fee[] memory _fees,
uint256 _maxDepositSizeBP,
uint256 _vaultMaxDeposits,
uint256 _operatorRewardPercentage,
address _vaultDepositController
>> ) public reinitializer(3) {

And here's the previous:

function initialize(
address _token,
address _stakingPool,
address _stakeController,
address _vaultImplementation,
Fee[] memory _fees,
uint256 _maxDepositSizeBP,
uint256 _operatorRewardPercentage
>> ) public reinitializer(3) {

As can be seen, some extra features have been added in the spirit of its upgradeability.

However, the same reinitilizer version 3 is used, both by the current and the previous.

Looking at OpenZeppelin's reinitilizer modifier in Initializable.sol

First, we learn that a version number cannot be reused.

  • The initialization functions use a version number. Once a version number is used, it is consumed and cannot be

  • reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in

  • case an upgrade adds a module that needs to be initialized.

And further, we look at the modifier, we can see that it requires that the _initialized parameter is less than the entered version before it sets the version to the _initialized parameter.

modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}

As seen in the previous contract implementation, reinitializer(3) was used, meaning that the _initialized parameter is now 3.

So, attempts to reinitialize the contract will always fail due to the required _initialized < version check in the reinitializer modifier.

For an extra bit of context, we can see from our search here that OperatorVCS has been deployed 3 times.

As a result, using reinitializer(3) in current OperatorVCS will cause intialization to always fail, and as such, contracts will be unusable.

Impact

OperatorVCS will be uninitializable making it more or less unusable

Tools Used

Manual Review

Recommendations

Upgrade the version > 3.

function initialize(
address _token,
address _stakingPool,
address _stakeController,
address _vaultImplementation,
Fee[] memory _fees,
uint256 _maxDepositSizeBP,
uint256 _vaultMaxDeposits,
uint256 _operatorRewardPercentage,
address _vaultDepositController
- ) public reinitializer(3) {
+ ) public reinitializer(4) {
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Some contracts will not be initialized due to an incorrect `reinitializer` versions used

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.