Liquid Staking

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

Array Out-of-Bounds Access in `_depositLiquidity` Function

Summary

The Vault.sol contract contains a vulnerability in the _depositLiquidity function where it accesses the _data array without ensuring that its length matches the number of strategies. This oversight can lead to an out-of-bounds array access, causing transaction reverts and potentially disrupting the staking operations.

Vulnerability Details

Problematic Code Snippet

function _depositLiquidity(bytes[] calldata _data) private {
uint256 toDeposit = token.balanceOf(address(this));
if (toDeposit > 0) {
for (uint256 i = 0; i < strategies.length; i++) {
IStrategy strategy = IStrategy(strategies[i]);
uint256 strategyCanDeposit = strategy.canDeposit();
if (strategyCanDeposit >= toDeposit) {
strategy.deposit(toDeposit, _data[i]);
break;
} else if (strategyCanDeposit > 0) {
strategy.deposit(strategyCanDeposit, _data[i]);
toDeposit -= strategyCanDeposit;
}
}
}
}

Issue Explanation

  • Assumption Flaw: The function assumes that the _data array provided has a length equal to or greater than the strategies array.

  • Risk of Reversion: If _data.length < strategies.length, accessing _data[i] for i >= _data.length will result in an out-of-bounds error, causing the transaction to revert.

  • Potential for Denial of Service: Malformed inputs with insufficient _data can prevent users from successfully depositing or withdrawing funds, leading to operational disruptions.

Proof of Concept (PoC)

1. Crafting a Malicious Deposit Transaction

Code Snippet:

// Attacker's malicious transaction
priorityPool.deposit(attackerAddress, 1000 * 10**18, new bytes[](2));

Explanation:
The attacker attempts to deposit 1000 LINK tokens but provides a _data array of length 2, which is shorter than the expected length of the strategies array (assumed to be 3). This triggers an out-of-bounds access when the loop in _depositLiquidity tries to access _data[2].

2. Observing Transaction Reversion

Code Snippet:

vm.expectRevert("Invalid deposit data length");
priorityPool.deposit(attackerAddress, 1000 * 10**18, shortData);

Explanation:
The test anticipates the transaction to revert with the specific error message "Invalid deposit data length". This confirms that the input validation effectively prevents out-of-bounds access.

3. Testing with Correct Input

Code Snippet:

// Preparing a correct _data array
bytes[] memory correctData = new bytes[]();
correctData[0] = "data1";
correctData[1] = "data2";
correctData[2] = "data3";
// Successful deposit
priorityPool.deposit(address(user), 1000 * 10**18, correctData);

Explanation:
Providing a _data array that matches the length of the strategies array ensures that the deposit function executes successfully without reverting, validating the effectiveness of the input validation.


Impact

  • Operational Disruption: Users may be unable to deposit or withdraw funds if the _data array does not meet the expected length, leading to failed transactions.

  • Denial of Service (DoS): Attackers can exploit this vulnerability by submitting transactions with intentionally short _data arrays, causing widespread transaction failures.

  • User Trust Erosion: Frequent transaction failures can diminish user confidence in the platform's reliability and security.

Tools Used

Manual Code Review:

Recommendations

1. Enforce Strict Input Validation

Implement a require statement at the beginning of the _depositLiquidity function to ensure the _data array's length meets the required criteria.

require(_data.length >= strategies.length, "Vault: _data array length insufficient for strategies");

2. Graceful Handling of Variable-Length Inputs

If variability in the _data array's length is intended, adjust the loop to iterate only up to the minimum of strategies.length and _data.length to prevent out-of-bounds access.

uint256 loopLimit = strategies.length < _data.length ? strategies.length : _data.length;
for (uint256 i = 0; i < loopLimit; i++) {
// Existing logic
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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