The Sabiler Protocol allows the sender to cancel a stream if it is marked as cancelable
. When the sender cancels the stream, any remaining assets are returned to sender of stream. However, if the assets are paused or the sender is blacklisted, the cancellation will fail. Most of the time, the stream operates based on a schedule. So the recipient will still receives the funds
The Sabiler Allows the sender of stream to cancel the stream if it is cancelable. The stream could be canceled if there is some miss agreement between the parties. When sender cancel the Stream the following step execute on smart contract level:
Senders calls the cancel function with the streamId
.
The code perform some internal checks to ensure that stream is Ok to cancel.
Calculate the remaining amount of stream. we will discuss it in subsequent details.
Transfer the assets to sender if any. Here The Issue reside.
Hit callback if recipient is smart contract.
3
here we calculate the amount to send back. The amount for each stream type is calculated using _calculateStreamedAmount
and _calculateStreamedAmount
has different implementation for each stream and the common thing is time all the calculation are performed on time basis from startTime
to endTime
here I will only explain the SablierV2LockupLinear
. following code will help to identify the amount withdraw able at given time:
It can be observed from above LN208
to LN229
that We first calculate the elapsed time , then take percentage of it with total duration and finally calculate the streamAmount so far. and return the streamAmount.
Now let have a look on Cancel function code :
After calculation of streamAmount
we subtract the return streamAmount
from amounts.deposited
and also check if there is some assets left for recipient.update the state of a stream and refunded
amount. At LN605
we send the senderAmount
to sender of stream. It is where the cancel function would revert in case of pause/blacklisting etc.
Let's have a look at following case :
Sender Bob creates a Linear stream with recipient Alice.
The stream will start from time 1 and ends at time 8.
There is some miss agreement between the parties, The Bob wants to cancel the stream at time 3.
When Bob submit the cancel transaction The transaction got revert due to any reason i.e transfers are paused/ Bob is blacklisted.
Now at time 6 the underline assets transfers are allowed and now Bob cancel the stream. the stream will only send the amount from time 6 to 8.
Alice will withdraw the amount from time 3 to 6. which in reality the Alice is not eligible to receive.
The recipient will keep receiving assets if the sender cannot cancel the stream due to transfer issues, even after a missed agreement.
Manual Review
One mitigation for this issue could be following :
Add struct with following key attributes :
and add mapping of sender to _cancelWithdrawal
.
add withdrawal function for cancel withdrawal only allow the sender of stream to withdraw.
Inside _cancel
function add following changes:
For other solution just Keep in Mind that due to some third party issue make sure the cancel stream will not revert. you can also completely remove the transfer from cancel call only update the states and allows the sender to withdraw funds in separate function.
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.