Sablier

Sablier
DeFiFoundry
53,440 USDC
View results
Submission Details
Severity: medium
Invalid

Lack of Data Validation in _calculateStreamedAmount Function

Summary

The _calculateStreamedAmount function in the SablierV2LockupDynamic contract does not explicitly validate whether the provided streamId corresponds to an existing stream. This lack of validation can lead to accessing uninitialized storage, returning incorrect values, and potentially causing unexpected behavior in the contract.

function _calculateStreamedAmount(uint256 streamId) internal view override returns (uint128) {
// If the start time is in the future, return zero.
uint40 blockTimestamp = uint40(block.timestamp);
if (_streams[streamId].startTime >= blockTimestamp) {
return 0;
}
// If the end time is not in the future, return the deposited amount.
uint40 endTime = _streams[streamId].endTime;
if (endTime <= blockTimestamp) {
return _streams[streamId].amounts.deposited;
}
if (_segments[streamId].length > 1) {
// If there is more than one segment, it may be required to iterate over all of them.
return _calculateStreamedAmountForMultipleSegments(streamId);
} else {
// Otherwise, there is only one segment, and the calculation is simpler.
return _calculateStreamedAmountForOneSegment(streamId);
}
}

Proof of Concept

  1. A user or another contract function calls a function that internally calls _calculateStreamedAmount with an invalid streamId.

  2. The function executes and returns a value based on uninitialized data from the _streams mapping, which could be zero or default values.

  3. The returned value is used to determine how much the recipient can withdraw or how much the sender has streamed, leading to incorrect financial outcomes.

  4. Users may withdraw less than they are entitled to or be unable to access funds that should be available, resulting in financial discrepancies and loss of trust in the platform.

Impact

The function does not perform a check to ensure that the provided streamId corresponds to an existing, initialized stream. If an invalid streamId is passed, the function may return incorrect values, which could lead to the misrepresentation of the streamed amount.

Tools Used

Manual review

Recommendations

  1. Implement a check within _calculateStreamedAmount to verify that the streamId corresponds to an existing and active stream. This could involve checking if stream properties such as startTime and endTime are initialized and make sense in the context of the current block timestamp.

  2. Consider reverting the transaction or providing a clear error message when the function is called with an invalid streamId, to prevent propagation of incorrect calculations.

function _calculateStreamedAmount(uint256 streamId) internal view override returns (uint128) {
// Verify the stream exists by checking its startTime
require(_streams[streamId].startTime != 0, "Stream does not exist");
// If the start time is in the future, return zero.
uint40 blockTimestamp = uint40(block.timestamp);
if (_streams[streamId].startTime >= blockTimestamp) {
return 0;
}
// If the end time is not in the future, return the deposited amount.
uint40 endTime = _streams[streamId].endTime;
if (endTime <= blockTimestamp) {
return _streams[streamId].amounts.deposited;
}
// Additional check for zero segments
require(_segments[streamId].length > 0, "Stream has no segments");
if (_segments[streamId].length > 1) {
// If there is more than one segment, it may be required to iterate over all of them.
return _calculateStreamedAmountForMultipleSegments(streamId);
} else {
// Otherwise, there is only one segment, and the calculation is simpler.
return _calculateStreamedAmountForOneSegment(streamId);
}
}

The updated _calculateStreamedAmount function includes additional checks to mitigate the issue of data validation:

It verifies that the stream exists by checking that its startTime is not zero.
It includes a check to ensure that the stream has at least one segment before proceeding with the calculation.

Updates

Lead Judging Commences

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

Support

FAQs

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