Flow

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

Dangerous Strict Equality : The _void(uint256) function in the SablierFlow contract uses a strict equality comparison (==) to check if the debtToWriteOff variable is equal to 0.

Summary : The _void(uint256) function in the SablierFlow contract is designed to write off debt when the debtToWriteOff variable is equal to 0. However, the function uses a strict equality comparison (==) to check if the debtToWriteOff variable is equal to 0.

Vulnerability Details : Let's break down the problem with using a strict equality comparison (==) in the context of the debtToWriteOff variable:

Precision Issues:

When working with floating-point numbers, precision issues can arise due to the way that numbers are represented in binary format. This can lead to small differences between the actual value and the represented value.

Example:

Suppose the debtToWriteOff variable is calculated to be 0.000001 due to a precision issue. In this case, the actual value is very close to 0, but the represented value is not exactly 0.

Strict Equality Comparison:

When using a strict equality comparison (==), the comparison will return false if the values being compared are not exactly equal. In the case of the debtToWriteOff variable, this means that the comparison will return false even though the value is essentially 0.

Impact : The problem with using a strict equality comparison (==) is that it does not account for potential precision issues or small differences between the values being compared. This can lead to incorrect behavior in the contract, including:

  • Incorrect debt calculations: The contract may calculate the debt incorrectly if the debtToWriteOff value is not exactly 0.

  • Incorrect snapshot debt updates: The contract may update the snapshot debt incorrectly if the debtToWriteOff value is not exactly 0.

Suppose the contract uses a strict equality comparison (==) to check if the debtToWriteOff variable is equal to 0. In this case, the comparison will return false even though the value is essentially 0.

if (debtToWriteOff == 0) {
// This code will not be executed even though debtToWriteOff 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 debtToWriteOff variable to a value very close to 0
uint256 debtToWriteOff = 0.000001;
// Call the _void function with the debtToWriteOff value
sablierFlow._void(debtToWriteOff);
// Check if the contract behaved incorrectly
require(sablierFlow.snapshotDebt() != debtToWriteOff, "Contract behaved correctly");
}

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

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

Tools Used : VS code

Recommendations : To fix this problem, 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.

if (debtToWriteOff <= 0) {
// This code will be executed even though debtToWriteOff 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.