The try/catch blocks in the SablierV2Lockup contract may fail to handle scenarios where the target contract does not implement the onLockupStreamCanceled(), onLockupStreamWithdrawn(), and onLockupStreamRenounced() hooks.
This can cause the transaction to revert unexpectedly, leading to a cascading failure in the contract.
The use of try/catch blocks in the SablierV2Lockup contract is intended to gracefully handle errors when calling external contracts. However, these blocks only catch errors that occur within the target contract's execution. If the target contract does not implement the expected hooks, such as onLockupStreamCanceled(), onLockupStreamWithdrawn(), and onLockupStreamRenounced(), the transaction will revert due to decoding errors rather than being caught by the catch block. This can lead to unexpected crashes in the contract.
The sender initiates the cancellation of a stream by calling the cancel function.
The function begins execution and performs initial checks to ensure the stream is neither depleted
nor already canceled and verifies that the sender is authorized to cancel the stream.
After marking the stream as canceled and transferring the funds, the cancel function attempts to call
the onLockupStreamCanceled() hook on the recipient contract.
If the recipient contract does not implement the hook, the transaction will revert due to decoding errors,
causing the entire cancellation process to fail.
_cancel Function:
If the recipient contract does not implement the expected hooks, the try/catch block will fail to catch the error, leading to a crash of the entire transaction and causing a cascading failure upon the rest of the onLockupStreamCanceled()
logic.
(and onLockupStreamWithdrawn())
Manual Review/Solidity Docs
This thread explains the solutions in more detail regarding circumventing try/catch blocks.
https://ethereum.stackexchange.com/questions/129150/solidity-try-catch-call-to-external-non-existent-address-method
https://docs.soliditylang.org/en/v0.8.14/control-structures.html?highlight=try catch#try-catch
Implement a check for the presence of contract code before attempting to call the hooks.
This can be done using extcodesize(assembly)
or use a wrapper contract which is internally calling the onLockupStreamCanceled
on the untrusted target.
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.