The SablierFlow::refund
function allows the sender of a stream to withdraw any funds that have not yet been streamed to the recipient. Unlike the SablierFlow::withdraw
function, where you can specify an address to receive the recipient's funds, the refund
function only allows funds to be returned to the original sender
address specified when the stream was created. There is no option to refund the funds to a different account.
This setup creates an issue if the sender's address becomes blocklisted by the token used in the stream. In such cases, the funds cannot be refunded to the blocklisted sender. Furthermore, if the stream is voided, these funds will be permanently locked in the protocol and cannot be withdrawn by any means.
The root cause of this issue is in the refund
function, which automatically uses the sender’s address to transfer the refunded funds, without providing an option to specify a different address for the refund.
Permanent lock of funds inside the protocol.
Alice wants to pay Bob a monthly bonus between 1000 USDC and 3000 USDC.
To facilitate this, Alice sets up a Sablier stream, depositing 3000 USDC.
Halfway through the month, Alice’s address interacts with TornadoCash
for privacy.
Due to this interaction, Alice’s address is promptly blocklisted on USDC contracts.
By the end of the month, Alice voids
the stream and 1500 USDC remains unstreamed.
Intends to refund the remaining balance. However, because Alice’s address is blocklisted, the refund is blocked by the USDC contracts, resulting in 1500 USDC being permanently locked in the Sablier protocol.
You can implement similar logic as in the withdraw
function, allowing the refund
function to send funds to a different address if the caller is the sender.
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.