Category: Coding Mistakes
No length check is present on the amounts parameter
Informational Impact
Informational Severity
N/A Likelihood
Description
The depositQueuedTokens and forceUnbond functions both take in an _amounts array that is expected to match the length of the _vaultIds array:
function depositQueuedTokens(
    uint256[] calldata _vaultIds,
    uint256[] calldata _amounts
) external onlyFundFlowController {
    // [...]
    for (uint256 i = 0; i < _vaultIds.length; ++i) {
        if (_vaultIds[i] == skipIndex) revert InvalidVaultIds();
        uint256 amount = _amounts[i];
        if (amount == 0) revert InvalidAmount();
        vaults[_vaultIds[i]].deposit(amount);
    }
    // [...]
}
function forceUnbond(
    uint256[] calldata _vaultIds,
    uint256[] calldata _amounts
) external onlyFundFlowController {
    // [...]
    for (uint256 i = 0; i < _vaultIds.length; ++i) {
        if (_vaultIds[i] == skipIndex) revert InvalidVaultIds();
        if (i > 0 && _vaultIds[i] <= _vaultIds[i - 1]) revert InvalidVaultIds();
        if (_amounts[i] == 0) revert InvalidAmount();
        vaults[_vaultIds[i]].unbond(_amounts[i]);
        totalUnbonded += _amounts[i];
    }
    // [...]
}However, there is no length check in either function.
Impact
If the _amounts parameter is longer than the _vaultIds parameter, then the extra entries will be disregarded. If it is shorter, then the above code will revert due to the array's bounds check. If the lengths do not match, then the calldata is malformed.
Recommendations
We recommend adding a length check to both these functions so that the erroneous case where the _amounts parameter is longer than the _vaultIds parameter fails noisily instead of quietly succeeding.
Remediation
This issue has been acknowledged by Stake.link, and a fix was implemented in commit 337298aa↗.