When msg.sender
, who is neither the stream's recipient nor the recipient's approved spender, calls the SablierV2Lockup.withdraw
function with the recipient's address as the to
input, the recipient can be forced to withdraw from such stream without the recipient's consent. If the recipient or sender is a contract that implements the onLockupStreamWithdrawn
function, such onLockupStreamWithdrawn
function can be called unexpectedly and adversely, such as causing the recipient to withdraw much earlier than intended and fail to become more vested coercively.
When msg.sender
is neither the stream's recipient nor such recipient's approved spender, calling the following SablierV2Lockup.withdraw
function with such recipient's address as the to
input would not revert with Errors.SablierV2Lockup_WithdrawalAddressNotRecipient
because to != recipient
is false. This causes the withdraw
function to be called without the consent of the stream's recipient. In this case, if the stream's recipient or sender is a contract that implements the onLockupStreamWithdrawn
function, the ISablierV2Recipient(recipient).onLockupStreamWithdrawn
or ISablierV2Sender(sender).onLockupStreamWithdrawn
function would be called, which can be unexpected and adverse to such recipient.
https://github.com/Cyfrin/2024-05-Sablier/blob/1fe69e059dcbd71728bdfaa58dad85ff199ee6dc/v2-core/src/abstracts/SablierV2Lockup.sol#L332-L402
For example, for incentivizing the recipient to not withdraw early, the stream's sender represented by a contract and recipient could agree on a vesting scheme that only allows the recipient to withdraw once in which the sender's onLockupStreamWithdrawn
function would call the SablierV2Lockup.cancel
function to cancel the corresponding stream and refund its unvested amount to the sender immediately after the withdraw
function is called for such stream. When someone, who is not the stream's recipient, calls the withdraw
function with the recipient's address as the to
input after just a small stream amount has become vested, the sender's onLockupStreamWithdrawn
function would be called. In this situation, the recipient fails to become more vested and cannot withdraw more stream amount even though she or he does not intend to withdraw early at all.
Manual Review
https://github.com/Cyfrin/2024-05-Sablier/blob/1fe69e059dcbd71728bdfaa58dad85ff199ee6dc/v2-core/src/abstracts/SablierV2Lockup.sol#L363-L365 can be updated to the following code.
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.