In Sablier version 1.1.2
, utilized by the Fjord protocol, the stream sender has the ability to forcefully withdraw streams they initiated. When this happens, the onStreamWithdrawn()
function callback is activated. However, in the FjordStaking
contract, the onStreamWithdrawn()
function lacks the necessary handling for this situation, potentially resulting in the loss of user funds.
The current implementation permits users to stake streams solely from authorizedSablierSenders
, yet it appears to assume that stream cancellation is the only possible action by an authorized stream sender.
However, Sablier's code also permits a stream sender to execute a force withdrawal:
If a partially trusted authorizedSablierSender
withdraws all stream IDs deposited into the FjordStaking contract, all transferred FJO tokens might be mistakenly considered as rewards, despite these tokens actually belonging to individual users.
This issue arises because the onStreamWithdrawn()
function fails to adequately handle such situations.
Improper handling of stream withdrawals can lead to incorrect staking calculations, potentially resulting in honest users losing a portion of their rewards.
Manual Review
As we can't fully prevent the force withdrawal of a stream, making it crucial to properly manage the onStreamWithdrawn()
callback. When the streamer calls on onStreamWithdrawn()
, identify the stream owner and the vesting stake epoch for the given streamID
. Adjust the accounting in the relevant user's DepositReceipt
, transferring the corresponding amount from vestedStaked
to staked
. Additionally, reduce the global totalVestedStaked
by the amount specified in the onStreamWithdrawn() function.
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.