When someone create stream using create or creadeAndDeposit it eventually create stream via _create function that looks like this:
As we can see function after necessary check create stream and mint NFT to the recipient via _mint
function that looks like this:
The issue arise because _mint
function only check if recipient address is not address(0)
, but it does not check if the recepient address is able to receive NFT.
This can cause the stream depositors to stuck their deposit forever in which case they will incur loss of funds.(especially the more time passes before they discover this and if stream is not transferable).
This can happen even if recipient is not malicious(althrough it can be also exploited by malicious user) as we can see in the examples below:
Example 1 non-malicious recipient:
There is a project that is 1 year long and deposited and covered amount in stream is 10 ETH. So after 1 year recipient should be able to withdraw deposited amount (it will not be full 10 ETH because of protocol fee, but for the sake of simplicity we can put protocol fee to 0 for now). Also anytme before 1 year passes recipient could withdraw some of the amount that is deposited based on how much time has passed, for example after 6 months he could withdraw 5 ETH (half of the deposited amount).
So stream owner creates stream with recipient address that is not able to receive NFT and make stream non transferable. If none of them (stream owner or recipient) does not find this immediatelly (which is usually the case unfortunatelly) and they find out for example 6 months after. Then in that case recipient would not be able to withdraw his promised funds, the depositors can refund their remaining amount but the half of their deposited amount would be stuck forever in contract since stream is not transferable, so in that case both parties incured loss of funds.
Example 2 malicious recipient:
Imagine same project as in example 1 but the recipient gave purposely wrong address that could not receive NFT and does not have intention to complete project task that he is payed for. The malicious recipient would not benefit this monetarly but the depositors will be the one that incured loss of funds especially if they found out they are scammed as late as possible during stream duration. They could refund some of the amount before duration ends but if duration ends they they will lose full deposit and it will be stucked.
In example I gave is small to medium project but the bigger the project and stream is the bigger losses can be (possibly in the range of millions of dollars).
Users can incur loss of funds and their funds stuck in contract forever.
Manual Review
In order to prevent this I recommend to use _safeMint
instead of regular _mint
because it checks if recipient received the NFT and revert if receiver is invalid address.
Further more I would recommend to have recover
function in SablierFlow
also that is specifically designed to recover deposited amount by the depositor in case funds got stuck in the contract.
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.