Flow

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

Dangerous Strict Equality(amount == 0 (src/SablierFlow.sol#781)) : The _withdraw function in the SablierFlow contract uses a strict equality comparison (==) to check if the amount variable is equal to 0.

Summary :

Vulnerability Details : The _withdraw function in the SablierFlow contract is designed to withdraw a specified amount of tokens from a stream. The function takes three parameters:

  • streamId: The ID of the stream from which to withdraw tokens.

  • to: The address to which the tokens should be transferred.

  • amount: The amount of tokens to withdraw.

The function uses a strict equality comparison (==) to check if the amount variable is equal to 0:

if (amount == 0) {
// Revert if the amount is 0
}

This comparison is used to prevent withdrawals of 0 tokens, which would be unnecessary and potentially wasteful.

Problem:

However, the use of a strict equality comparison (==) can be problematic. In Solidity, the == operator checks for exact equality between two values. This means that if the amount variable is very close to 0, but not exactly equal, the comparison will return false.

For example, suppose the amount variable is calculated to be 0.000001 due to a precision issue. In this case, the strict equality comparison (==) will return false, even though the value is essentially 0.

Impact : This can lead to incorrect behavior in the contract, including:

  • Incorrect withdrawal amounts: The contract may allow withdrawals of amounts that are very close to 0 but not exactly equal.

  • Reverts: The contract may revert when attempting to withdraw an amount that is very close to 0 but not exactly equal.

Example:

Suppose the amount variable is calculated to be 0.000001 due to a precision issue. In this case, the strict equality comparison (==) will return false, even though the value is essentially 0.

if (amount == 0) {
// This code will not be executed even though amount is essentially 0
}

Proof of Concept Code : Here is a proof of concept code that demonstrates the vulnerability..

contract ExploitContract {
SablierFlow public sablierFlow;
constructor(address sablierFlowAddress) public {
sablierFlow = SablierFlow(sablierFlowAddress);
}
function exploit() public {
// Set the amount variable to a value very close to 0
uint128 amount = 0.000001;
// Call the _withdraw function with the amount value
sablierFlow._withdraw(1, address(this), amount);
// Check if the contract behaved incorrectly
require(sablierFlow.withdrawnAmount() != amount, "Contract behaved correctly");
}

This code creates a new contract called ExploitContract that has a reference to the SablierFlow contract. The exploit function sets the amount variable to a value very close to 0 and then calls the _withdraw function with that value.

The require statement checks if the contract behaved incorrectly by verifying that the withdrawnAmount value is not equal to the amount value. If the contract behaved correctly, the require statement will throw an exception.

Tools Used : VS Code

Recommendations : To fix this issue, it's recommended to use a more robust comparison method, such as >= or <=, to account for potential precision issues or small differences between the values being compared.

Updated Code:

if (amount <= 0) {
// This code will be executed even though amount is not exactly 0
}

By using a more robust comparison method, the contract can ensure that the comparison is accurate even in the presence of precision issues or small differences between the values being compared.

Updates

Lead Judging Commences

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.