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.