Incorrect user passed to "onUnstaked" when a stream is canceled
When a stream is canceled and the onStreamCanceled function is called, the streamOwner is passed to the _unstakeVested function. However, in the _unstakeVested function, when the points.onUnstaked https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordStaking.sol#L561 function is invoked, which is responsible for reducing the amount in the points contract, msg.sender is passed instead of streamOwner. In this case, msg.sender will be the Sablier contract, which will cause the system to attempt to subtract the amount not from the user's account but from the Sablier contract's account, which has a balance of zero. Subtracting the amount from zero will cause the entire transaction to revert. As a result, the user will continue accumulating rewards as if they are still staking, even though they no longer have the right to the refunded tokens.
To create a new test file that showcases the vulnerability within the FjordStaking.sol contract, we can focus on simulating the scenario described. Create a new test file inside the unit folder
User acquires staking rewards after the stream is canceled, for the amount that was refunded to the stream sender.
Manual Review
In the _unstakeVested (https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordStaking.sol#L521) function change
in line https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordStaking.sol#L561
points.onUnstaked(msg.sender, amount);
to points.onUnstaked(streamOwner, amount);
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.