Malicious actors can withdraw tokens of vested Sablier stream directly to the FjordStaking contract by setting the to parameter of SablierV2Lockup::withdraw() function to the address of the FjordStaking contract. Since theFjordStaking contract does not track these withdrawals, the tokens become locked.
The SablierV2Lockup::withdraw() and SablierV2Lockup::withdrawMax() functions allow anyone to withdraw tokens from a vested Sablier stream to the owner of Sablier stream.
Here’s how the issue arises:
The malicious actor calls withdraw() or withdrawMax() with the to parameter set to the FjordStaking contract address.
The contract checks if the to address matches the recipient (the stream owner, which is the FjordStaking contract in this case) or if the caller is an approved party:
SablierV1Lockup::withdraw()#L375
Since the FjordStaking contract is the stream owner, the validation passes, and the tokens are withdrawn to the FjordStaking contract.
However, the FjordStaking contract does not track these withdrawn tokens or allocate them to the correct stakers.
Root Cause: Sablier allows anyone to withdraw tokens of a stream to the stream owner, but the FjordStaking contract does not track the withdrawn tokens for stakers to handle this scenario.
When users unstake their vested Sablier streams, they cannot receive the withdrawn tokens, which become permanently locked in the FjordStaking contract.
vscode
Tracks the withdrawn tokens of vested Sablier stream, send these tokens to stakers when they unstake the vested steams.
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.