Liquid Staking

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

##Reinitialization Logic Vulnerability in the function 'initialize' .

Summary

The initialize function uses the reinitializer(3) modifier, which means it can be called again if the contract’s initialization version is 2.

The function contains two distinct branches of logic:

The first branch is executed if address(token) is address(0).
The second branch is executed if address(token) is not address(0). If the function is called multiple times, it might result in the second branch being executed unintentionally. This could cause unintended changes in the contract’s state, such as updating globalVaultState and maxDepositSizeBP in a way that might not be intended by the contract logic.
Depending on how token and __VaultControllerStrategy_init are set up, this could result in unexpected behavior in cases where token is not address(0).

Vulnerability Details

Calling the initialize function multiple times can indeed lead to unintended execution of the second branch of the conditional logic, especially if the state of the contract is not managed correctly. Let's break down how this could happen and what the implications are.
https://github.com/Cyfrin/2024-09-stakelink/blob/main/contracts/linkStaking/OperatorVCS.sol#L52-L88

Understanding the Function Logic

The initialize function has a conditional check based on whether the token address is set:

if (address(token) == address(0)) {
// Initialization logic
} else {
// Update logic
}

Scenario: Multiple Calls to initialize

  1. First Call:

    • When the contract is first deployed, the token address is uninitialized (zero address).

    • The first branch executes, initializing various parameters and setting up the contract state.

  2. Subsequent Calls:

    • If you call initialize again after it has been initialized (i.e., after setting token), the condition will evaluate to false, and the second branch will execute.

    • This branch updates globalVaultState, maxDepositSizeBP, and vaultMaxDeposits, but it does not reinitialize other critical parameters that may have been set during the first call.

Example of a Problematic Sequence

  1. First Initialization:

    • _operatorRewardPercentage is set to a valid value (e.g., 5000).

    • The contract initializes correctly with all necessary state variables.

  2. Second Initialization Call:

    • If _operatorRewardPercentage is now set to an invalid value (e.g., 15000), this will cause a revert at the check:

      if (_operatorRewardPercentage > 10000) revert InvalidPercentage();
    • However, if there were changes made prior to this check (like setting globalVaultState), those changes would persist even though the transaction ultimately fails.

  3. Third Initialization Call:

    • If called again with valid parameters, it will execute the second branch again without reinitializing any previously set values, leading to potential logical inconsistencies.

Impact

Subsequent calls may execute without reinitializing critical parameters, resulting in unpredictable outcomes.
Changes to parameters like maxDepositSizeBP could affect how deposits are managed, impacting users' rewards, deposits, or withdrawals. This could result in users receiving incorrect rewards or being unable to deposit or withdraw as expected.
Exploits which could be used to manipulate the state of globalVaultState or maxDepositSizeBP, leading to unauthorized behavior or gaining an advantage over other users.

Tools Used

Manual

Recommendations

Use access control mechanisms (like modifiers) to restrict who can call initialize, ensuring it's only called once or under specific conditions.
Single Initialization Check: Utilize a boolean flag (e.g., initialized) that tracks whether initialization has already occurred, preventing further calls from executing any logic unintentionally.
Require Statements: Add require statements at the beginning of the function to enforce conditions that must be met for execution, ensuring that only valid states proceed through initialization logic.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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