The incorrect input argument of the function call FjordPoints#onUnstaked in FjordStaking#_unstakeVested will cause the vested stream is not unstaked successfully from FjordStaking when a Sablier sender cancels a vested stream.
A Sablier sender can cancel a vested stream by calling SablierV2Lockup#cancel, then the sablier contract will call to FjordStaking#onStreamCanceled
FjordStaking#onStreamCanceled will call to FjordStaking#_unstakeVested
and then FjordPoints#onUnstaked
https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordStaking.sol#L561
But the input argument to the FjordPoints#onUnstaked(address user, uint256 amount) is msg.sender, which is the sablier contract's address. This will cause a revert at the function call FjordPoints#onUnstaked, because the sablier contract is not staking any points, the correct user input argument here should be streamOwner. Since the sablier contract wraps the callback in a try-catch block, the vested stream is cancelled successfully in the sablier contract. However, in the FjordStaking contract, the vested stream is still staked.
When a Sablier sender cancels a vested stream, the vested stream is not unstaked successfully from FjordStaking, which causes the vested stream is still accruing staking rewards and Fjord points.
Manual Review.
Fix the input argument of the function call FjordPoints#onUnstaked in FjordStaking#_unstakeVested
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.