Flow

Sablier
FoundryDeFi
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

Incorrect Check Prevents voiding a stream in `SablierFlow.sol::_void` Function, lead Dos and break function usage

Summary

Vulnerability Details

https://github.com/Cyfrin/2024-10-sablier/blob/8a2eac7a916080f2022527408b004578b21c51d0/src/SablierFlow.sol#L728-L733

According to the documentation, a stream should be voidable by the sender, recipient, or an approved third party. However, in the SablierFlow.sol::_void function, an if statement incorrectly requires the msg.sender to be both the sender and either the recipient or an approved third party. Since msg.sender cannot simultaneously be the sender, recipient, and an approved third party, this check effectively blocks authorized parties from voiding the stream. Using an || operator instead of && would correctly check if msg.sender is either the sender, recipient, or an approved third party.

```solidity

if (msg.sender != _streams[streamId].sender && !_isCallerStreamRecipientOrApproved(streamId)) {

revert Errors.SablierFlow_Unauthorized({ streamId: streamId, caller: msg.sender });

}

```

Impact

Streams cannot be voided, potentially leaving them active indefinitely, which disrupts protocol functionality and results in undeletable streams.

Tools Used

Manual Review, VSCode

Recommendations

Replace the && operator with || to ensure that any authorized party (sender, recipient, or approved third party) can void the stream as intended.

```solidity

function _void(uint256 streamId) internal {

if (msg.sender != _streams[streamId].sender || !_isCallerStreamRecipientOrApproved(streamId)) {

revert Errors.SablierFlow_Unauthorized({ streamId: streamId, caller: msg.sender });

}

uint256 debtToWriteOff = _uncoveredDebtOf(streamId);

if (debtToWriteOff == 0) {

uint256 ongoingDebtScaled = _ongoingDebtScaledOf(streamId);

if (ongoingDebtScaled > 0) {

_streams[streamId].snapshotDebtScaled += ongoingDebtScaled;

}

} else {

_streams[streamId].snapshotDebtScaled = Helpers.scaleAmount({ amount: _streams[streamId].balance, decimals: _streams[streamId].tokenDecimals });

}

_streams[streamId].snapshotTime = uint40(block.timestamp);

_streams[streamId].ratePerSecond = ud21x18(0);

_streams[streamId].isVoided = true;

emit ISablierFlow.VoidFlowStream({

streamId: streamId,

sender: _streams[streamId].sender,

recipient: _ownerOf(streamId),

caller: msg.sender,

newTotalDebt: _totalDebtOf(streamId),

writtenOffDebt: debtToWriteOff

});

}

```

Updates

Lead Judging Commences

inallhonesty Lead Judge
8 months ago
inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.