Attacker can honeypot NFT buyer by create stream, selling them and cancel when front-running anyone buying them
Function cancel()
is used to cancel stream that created by caller:
function cancel(uint256 streamId) public override noDelegateCall notNull(streamId) {
// Check: the stream is neither depleted nor canceled.
if (_streams[streamId].isDepleted) {
revert Errors.SablierV2Lockup_StreamDepleted(streamId);
} else if (_streams[streamId].wasCanceled) {
revert Errors.SablierV2Lockup_StreamCanceled(streamId);
}
// Check: `msg.sender` is the stream's sender.
if (!_isCallerStreamSender(streamId)) {
revert Errors.SablierV2Lockup_Unauthorized(streamId, msg.sender);
}
// Checks, Effects and Interactions: cancel the stream.
_cancel(streamId);
}
function _cancel(uint256 streamId) internal {
// Calculate the streamed amount.
uint128 streamedAmount = _calculateStreamedAmount(streamId); // <---
. . . . . . .
uint128 senderAmount;
unchecked {
senderAmount = amounts.deposited - streamedAmount; // <---
}
. . . . . . .
// Interaction: refund the sender.
asset.safeTransfer({ to: sender, value: senderAmount }); // <---
. . . . . . .
}
Attacker can honeypot other user by create stream, with some amount, selling them on markets with interesting price. When someone decide to buy them, attacker will front-running by call withdraw()
and cancel()
function to withdraw all assets that avaiable in that streamId.
Victim will receive stream NFT with no token that can be withdrawn from it
Manual review
Do not allow to transfer canceled stream to avoid this attack vector.
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.