This report addresses a logic error in the _calculateStreamedAmountForMultipleSegments
function within the SablierV2LockupDynamic smart contract. The issue pertains to the calculation of the streamed amount for multiple segments based on timestamps and amounts stored in the contract. The flaw leads to incorrect calculations of the streamed amount, affecting the functionality of the lockup mechanism and potentially causing financial discrepancies.
The core of the vulnerability lies in the handling of timestamps and the calculation of elapsed time and segment durations. Specifically, the method calculates the elapsed time and segment duration incorrectly under certain conditions, particularly when dealing with segments that are not the first in the sequence. This miscalculation can result in an overestimation of the elapsed time percentage and subsequently an incorrect calculation of the streamed amount for the current segment.
The function iterates through segments until it finds one whose timestamp is less than the current block timestamp. It then calculates the elapsed time and segment duration based on these timestamps and uses them to calculate the streamed amount for the current segment.
The issue arises from the way the previousTimestamp
is determined. When the current segment is not the first (index!= 0
), the amount of time that has passed since the segment started would be wrong in the case, cause we use the previous segment's timestamp, and not the overall start timestamp as used when the index == 0, hinted above, essentially leading to a flawed data for the segment's duration(making it smaller than it should be) which would cause for elapsedTimePercentage to be bigger than it should be and also the segmentStreamedAmount
this then causes some segments to be unfairly/wrongly voided considering the if (segmentStreamedAmount.gt(currentSegmentAmount))
check might be triggerred depending on how massive the segmentStreamedAmount
gets incremented, if the if block isn't triggered this still leads to a wrong evaluation of the total streamed amount since it's gotten by adding the previous segment amounts and the amount streamed in the current segment (segmentStreamedAmount
, which in our case would be flawed).
As already hinted in the Proof of Concept, this leads to multiple issues as all the calculations done in the snippet shown below would now be done with a flawed elapsedTime
& segmentDuration
data.
Manual review
The check if the index is > 1 when calculating the previousTimestamp
, if true should then cache in the startTime from index == 0
to get the current duration length.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.