The onStreamCanceled
function is called from the Sablier contract to unstake a stream owners vested FJORD tokens. This function invokes _redeem
to first update the streamOwner
’s rewards, followed by _unstakeVested
to partially or fully unstake the vested FJORD tokens.
The problem is that the onStreamCanceled
function has the onlySablier
modifier, meaning msg.sender
will always be the Sablier address. However, in the _unstakeVested
function, msg.sender
is used to update the points by calling points.onUnstaked
, as shown above.
As a result, the onUnstaked
function will mistakenly assign the Sablier address as the user
variable. This leads to a function revert since the initial points when staked were correctly attributed to the streamOwner
.
Since the onStreamCanceled
function is invoked in a try-catch block, this revert causes the points.onUnstaked
call to be skipped. Consequently, the user's totalStaked
in the FjordPoints
contract remains unchanged, allowing them to continue earning points on the unstaked amount, thus receiving more rewards than they should.
Severity: Medium. Users will gain more rewards than they should, and this can also be used to exploit the system to earn extra rewards.
Likelihood: High. This will occur every time the onStreamCanceled
function is called.
Manual analysis
To resolve this issue, ensure that the streamOwner
is passed to the points.onUnstaked
function instead of msg.sender
. This will correctly attribute the unstaking to the streamOwner
and adjust their points accordingly.
Indeed the `points.onUnstaked` should use the streamOwner instead of msg.sender as an input parameter. Impact: high - The vested stakers who got their streams canceled will keep on receiving rewards (points included) for the previously staked stream. Likelihood: low - whenever a Sablier stream sender decides to `cancel()` a recipient's stream
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.