The depletionTimeOf function in SablierFlow contains a vulnerability where a division by zero can occur despite having a notPaused modifier. This creates a potential DoS condition and contract instability.
The issue stems from a mismatch between stream state validation and mathematical operations.
First, the function comes with a notPaused
modifier:
The stream can enter a zero-rate state through legitimate operations. For example, via adjustRatePerSecond
:
Later in depletionTimeOf
, we perform division using the rate:
The issue can occur through this sequence:
What makes this particularly dangerous is that the stream can enter this state through normal operations. The notPaused
modifier is checking the wrong condition - a stream can have a zero rate without technically being "paused". This creates a mathematical impossibility: trying to calculate how long until a stream depletes when it's not moving at all.
The division by zero vulnerability in depletionTimeOf()
creates a cascading effect throughout the protocol's core streaming mechanics. When a stream enters a zero-rate state through legitimate operations like adjustRatePerSecond()
, the depletion time calculation becomes impossible, causing the function to revert. This reversion breaks a fundamental invariant of the streaming protocol - the ability to determine when a stream will become insolvent.
The failure of this calculation has far-reaching implications. Smart contracts integrating with Sablier that rely on depletionTimeOf()
to make streaming decisions will fail to execute their logic. For instance, automated portfolio management systems that rebalance based on stream depletion forecasts will be unable to make informed decisions. Compound-like protocols that use stream solvency as part of their risk calculations would have inaccurate or failing risk models.
More critically, since depletionTimeOf()
is a key component in determining stream health, its failure compromises the protocol's ability to maintain accurate solvency data. This could lead to scenarios where streams appear healthy in some protocol functions but revert in others, creating inconsistent contract state. Automated liquidation or refinancing systems would be particularly vulnerable, as they would be unable to properly assess when to take action.
The timing aspect compounds the severity - the issue manifests not at stream creation or rate adjustment, but at the point of querying depletion time. This means a stream could appear perfectly healthy until someone attempts to check its depletion status, at which point the operation fails. This delayed failure pattern is especially dangerous as it could allow the creation of streams that later become impossible to properly manage or monitor.
In production environments, this could trigger a domino effect where initial function failures lead to stuck transactions, failed automated processes, and ultimately frozen funds as safety checks and management functions become inoperable. The economic impact extends beyond direct protocol interactions to any financial planning or risk assessment systems that depend on accurate stream depletion forecasts.
The proper fix requires explicit rate handling:
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.