Liquid Staking

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

Incorrect Initialization of `GlobalVaultState` in `CommunityVCS` Contract

Summary

The CommunityVCS contract initializes the depositIndex field of the GlobalVaultState struct using a value derived from maxDepositSizeBP, which is conceptually incorrect. The depositIndex should represent the index of the next non-group vault to receive deposits, and it should be initialized based on the current number of deployed vaults if address (token) != address (0).

Vulnerability Details

In the CommunityVCS contract, the globalVaultState is initialized as follows:

function initialize(
address _token,
address _stakingPool,
address _stakeController,
address _vaultImplementation,
Fee[] memory _fees,
uint256 _maxDepositSizeBP,
uint256 _vaultMaxDeposits,
uint128 _vaultDeploymentThreshold,
uint128 _vaultDeploymentAmount,
address _vaultDepositController
) public initializer {
if (address(token) == address(0)) {
__VaultControllerStrategy_init(
_token,
_stakingPool,
_stakeController,
_vaultImplementation,
_fees,
_maxDepositSizeBP,
_vaultMaxDeposits,
_vaultDepositController
);
vaultDeploymentThreshold = _vaultDeploymentThreshold;
vaultDeploymentAmount = _vaultDeploymentAmount;
_deployVaults(_vaultDeploymentAmount);
globalVaultState = GlobalVaultState(5, 0, 0, 0);
} else {
globalVaultState = GlobalVaultState(5, 0, 0, uint64(maxDepositSizeBP + 1));
maxDepositSizeBP = _maxDepositSizeBP;
delete fundFlowController;
vaultMaxDeposits = _vaultMaxDeposits;
}
for (uint64 i = 0; i < 5; ++i) {
vaultGroups.push(VaultGroup(i, 0));
}
}

This is also seen in the operatorVCS contract as shown below:

https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/linkStaking/OperatorVCS.sol#L52-L84

function initialize(
address _token,
address _stakingPool,
address _stakeController,
address _vaultImplementation,
Fee[] memory _fees,
uint256 _maxDepositSizeBP,
uint256 _vaultMaxDeposits,
uint256 _operatorRewardPercentage,
address _vaultDepositController
) public reinitializer(3) {
if (address(token) == address(0)) {
__VaultControllerStrategy_init(
_token,
_stakingPool,
_stakeController,
_vaultImplementation,
_fees,
_maxDepositSizeBP,
_vaultMaxDeposits,
_vaultDepositController
);
if (_operatorRewardPercentage > 10000) revert InvalidPercentage();
operatorRewardPercentage = _operatorRewardPercentage;
globalVaultState = GlobalVaultState(5, 0, 0, 0);
} else {
globalVaultState = GlobalVaultState(5, 0, 0, uint64(maxDepositSizeBP + 1));
maxDepositSizeBP = _maxDepositSizeBP;
delete fundFlowController;
vaultMaxDeposits = _vaultMaxDeposits;
}

The depositIndex of the struct GlobalVaultState is set to uint64(maxDepositSizeBP + 1), which is incorrect because maxDepositSizeBP is related to deposit size limits in basis points, not vault indexing. This could lead to incorrect deposit behavior, as the depositIndex is used to track where the next deposit should occur.

Impact

The incorrect initialization of depositIndex can lead to deposits being directed to the wrong vaults, potentially causing deposit distribution and management issues. This could affect the vault system's overall functionality and efficiency.

Tools Used

  • Manual code review

Recommendations

Update the initialization of globalVaultState to use the correct value for depositIndex. It should be based on the index of the next non-group vault to receive deposits

Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

[INVALID] Incorrect Initialization of `GlobalVaultState` in `CommunityVCS` Contract

Support

FAQs

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