Flow

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

Potential Reentrancy Vulnerability in withdraw Function

Description

location : src/SablierFlow.sol

The withdraw function allows users to withdraw tokens from a stream. The function performs several state updates and then transfers tokens to the recipient. However, there is a risk of reentrancy because the external call to token.safeTransfer happens after state updates but the state updates may be insufficient to prevent reentrant calls.

code :

function _withdraw(
uint256 streamId,
address to,
uint128 amount
)
internal
returns (uint128 withdrawnAmount, uint128 protocolFeeAmount)
{
//snip
// Interaction: perform the ERC-20 transfer.
token.safeTransfer({ to: to, value: amount });
//snip
}

While the function updates internal state variables before making the external call, if the token being transferred is an ERC777 token or a malicious ERC20 token that has a reentrancy vector via transfer or transferFrom, the contract may still be vulnerable.

Impact

An attacker could exploit this vulnerability by re-entering the withdraw function during the safeTransfer call and manipulating the contract's state to withdraw more funds than intended.

Recommendation

  • Use Reentrancy Guard: Incorporate a reentrancy guard in the function to prevent reentrant calls.

For example, use the nonReentrant modifier from OpenZeppelin's ReentrancyGuard contract.

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SablierFlow is ReentrancyGuard {
// rest of the contract
function withdraw(
uint256 streamId,
address to,
uint128 amount
)
external
override
noDelegateCall
notNull(streamId)
updateMetadata(streamId)
nonReentrant
returns (uint128 withdrawnAmount, uint128 protocolFeeAmount)
{
// rest of the function code
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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