note the issue can also occur on NFT lending marketplaces with a few variations but the attack path is similar
Victims think they are buying a worth stream but they end up with an empty stream.
This results in a loss of funds for the victims, profit for the malicious user and loss of trust in the Sablier protocol.
In the majority of NFT marketplaces such as Opensea and Blur, users can list their NFT by approving it to the marketplace contract.
Once the NFT finds a buyer, the marketplace contract transfers the NFT from the owner to the buyer who pays to receive it.
Regarding Sablier, a stream is represented as an NFT and can have the ability to be :
transfered (by the NFT owner) : the new NFT owner will be able to withdraw streamed (an unclaimed) funds
canceled (by the stream creator) : the stream creator will be able to withdraw the un-streamed funds, setting the stream in a state where it won't stream funds anymore (the current owner is still able to withdraw the already streamed funds)
Here is a realistic scenario where a malicious user can honeypot other users to steal their funds.
note that this scenario can be crafted in a more malicious way but for the sake of simplicity, we'll keep it this way
Attacker creates a linear stream that lasts for 5 days, holds 5,000 USDC and sets the recipient to himself
Attacker lists the stream on Opensea for the equivalent of 1,000 USDC
User sees he can make a 4,000 USDC profit and buys the stream for 1,000 USDC
Attacker was monitoring the mempool and frontruns the user's transaction to withdraw the already streamed tokens (he can do it since he is the stream recipient) and cancel it to recover the un-streamed tokens (he can do it since he is the stream creator)
The marketplace executes the trade, sends the 1,000 USDC equivalent to the attacker and sends the stream to the user
At the end of the scenario, the attacker basically stole $1,000 from the user
Manual review
Considering the protocol design, the issue can't be patched easily.
In order to prevent one part of the attack, the stream would need to be UNCANCELABLE
but this can't be enforced as it is a core functionality.
The second part of the attack can't really be countered because while the NFT is listed on the marketplace, it might still stream funds which can be claimed by NFT owner at any time.
One idea would be to add a requirement on the NFT approval function that checks if the address approved is part of a list of allowed marketplaces. If that is the case, the stream would need to be canceled
(and maybe have 0 streamed tokens
?)
Adding functions to make the process easier for users would be beneficial.
https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity
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.