Flow

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

Missing Input Validation: Lack of Validation Checks for Recipient in `create` Function

Summary

The SablierFlow::create function allows any user to create a streams, but the SablierFlow::_create function only checks if the sender's address is not a zero address. It doesn't verify if the recipient's address is a zero address, meaning users could accidentally input a zero address instead of the intended recipient.

Vulnerability Details

If a sender decides to create a stream using the SablierFlow::create , SablierFlow::createAndDeposit functions and enters all the required details, but accidentally inputs the zero address as the recipient, it could lead to a poor user experience and unintentional loss of funds

function _create(
address sender,
address recipient,
UD21x18 ratePerSecond,
IERC20 token,
bool transferable
)
internal
returns (uint256 streamId)
{
// Check: the sender is not the zero address.
if (sender == address(0)) {
revert Errors.SablierFlow_SenderZeroAddress();
}
@audit No validation check for recipient address
uint8 tokenDecimals = IERC20Metadata(address(token)).decimals();
// Check: the token decimals are not greater than 18.
if (tokenDecimals > 18) {
revert Errors.SablierFlow_InvalidTokenDecimals(address(token));
}
// Load the stream ID.
streamId = nextStreamId;
// Effect: create the stream.
_streams[streamId] = Flow.Stream({
balance: 0,
isStream: true,
isTransferable: transferable,
isVoided: false,
ratePerSecond: ratePerSecond,
sender: sender,
snapshotDebtScaled: 0,
snapshotTime: uint40(block.timestamp),
token: token,
tokenDecimals: tokenDecimals
});
// Using unchecked arithmetic because this calculation can never realistically overflow.
unchecked {
// Effect: bump the next stream ID.
nextStreamId = streamId + 1;
}
// Effect: mint the NFT to the recipient.
_mint({ to: recipient, tokenId: streamId });
// Log the newly created stream.
emit ISablierFlow.CreateFlowStream({
streamId: streamId,
sender: sender,
recipient: recipient,
ratePerSecond: ratePerSecond,
token: token,
transferable: transferable
});
}

In this scenario:

  1. The sender creates the stream and passes the zero address check in the internal Sablier::_create function.

  2. The sender provides all the necessary inputs to initiate the stream.

  3. The sender mistakenly enters the zero address as the recipient.

  4. As a result, the sender may unintentionally send funds to the zero address, thinking they are sending them to the intended recipient.

Impact

It can lead to unintentional loss of funds

Tools Used


Manuel review

Recommendations

Include a validation check that checks for address zero for the recipient address and also include the error message in the Errors.sol as SablierFlow_RecipientZeroAddress

function _create(
address sender,
address recipient,
UD21x18 ratePerSecond,
IERC20 token,
bool transferable
)
internal
returns (uint256 streamId)
{
// Check: the sender is not the zero address.
if (sender == address(0)) {
revert Errors.SablierFlow_SenderZeroAddress();
}
+ if (recipient == address(0)) {
revert Errors.SablierFlow_RecipientZeroAddress();
}
uint8 tokenDecimals = IERC20Metadata(address(token)).decimals();
// Check: the token decimals are not greater than 18.
if (tokenDecimals > 18) {
revert Errors.SablierFlow_InvalidTokenDecimals(address(token));
}
// Load the stream ID.
streamId = nextStreamId;
// Effect: create the stream.
_streams[streamId] = Flow.Stream({
balance: 0,
isStream: true,
isTransferable: transferable,
isVoided: false,
ratePerSecond: ratePerSecond,
sender: sender,
snapshotDebtScaled: 0,
snapshotTime: uint40(block.timestamp),
token: token,
tokenDecimals: tokenDecimals
});
// Using unchecked arithmetic because this calculation can never realistically overflow.
unchecked {
// Effect: bump the next stream ID.
nextStreamId = streamId + 1;
}
// Effect: mint the NFT to the recipient.
_mint({ to: recipient, tokenId: streamId });
// Log the newly created stream.
emit ISablierFlow.CreateFlowStream({
streamId: streamId,
sender: sender,
recipient: recipient,
ratePerSecond: ratePerSecond,
token: token,
transferable: transferable
});
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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