Flow

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

Vulnerability in Token _withdrawal() Logic and Protocol Invariant Checks in SablierFlow.sol contract

Summary

in the _withdraw function of the SablierFlow.sol smart contract. there’s a vulnerability tied to how a protocol invariant is handled after transferring tokens. Specifically, the assertion that ensure that the total debt remains consistent with the stream balance is being checked after the token transfer happens. This could lead to financial discrepancies and create opportunities for further exploits.

Vulnerability Details

Code Snippet of Concern:

.
.
.
.
// Perform the ERC-20 transfer after all checks are confirmed.
token.safeTransfer({ to: to, value: amount });
// Protocol Invariant: the difference in total debt should be equal to the difference in the stream balance.
assert(totalDebt - _totalDebtOf(streamId) == balance - _streams[streamId].balance);

In the current implementation of the _withdraw function in the SablierFlow.sol contract, a critical assertion regarding a protocol invariant (which checks that the total debt remains consistent with the stream balance) is positioned after the token transfer operation. This means that the assertion is executed after the contract has already sent tokens to the recipient.

If the assertion fails, the contract will revert while the external transfer remains intact. This means that the recipient would possess tokens that are not accurately reflected in the contract's internal state. As a result, this could lead to confusion and discrepancies regarding token ownership and available balances.

Moreover, these state inconsistencies could allow users to unintentionally gain unauthorized access to funds, posing a serious risk to both the protocol and its users.

In addition to the financial implications, this vulnerability could severely impact the project's reputation. Incidents of financial discrepancies or exploitation can lead to a significant loss of user trust, ultimately hindering the protocol's adoption and growth.

Impact

The vulnerability associated with the assertion failure in the _withdraw function poses several significant risks that can have far-reaching consequences for the protocol and its users:

  1. Inconsistent State:

    • If the assertion fails after the token transfer, the contract's internal state may no longer align with the actual token balances held by users. The external transfer will remain intact, meaning the recipient will have tokens that the contract cannot account for. This inconsistency can create confusion for users and complicate the protocol's accounting, leading to a lack of clarity regarding token ownership and available balances.

  2. Unauthorized Access to Funds:

    • The state inconsistencies resulting from a failed assertion can unintentionally enable users to gain unauthorized access to funds. This can occur if the protocol mistakenly allows withdrawals or transfers based on outdated or inaccurate balance information, resulting in financial losses for the protocol and its users.

  3. Increased Exploitability:

    • Attackers may exploit this vulnerability to manipulate the protocol’s financial logic. By understanding the conditions under which the assertion fails, malicious actors could craft specific transactions that enable them to withdraw or transfer funds they should not have access to, increasing the risk of reentrancy attacks and other forms of exploitation.

  4. Reputational Damage:

    • Should this vulnerability be exploited or lead to significant financial discrepancies, it could severely tarnish the project’s reputation. Users who experience financial losses or confusion may lose trust in the protocol, and negative word-of-mouth can spread quickly within the community. This loss of credibility can deter potential users and investors, ultimately hindering the protocol's growth and adoption.

  5. Regulatory Risks:

    • In cases where users lose funds due to vulnerabilities or mismanagement, there could be legal or regulatory repercussions. Regulatory bodies may scrutinize the protocol for failing to protect user assets, leading to potential penalties or restrictions on operations.

In summary, the impact of this vulnerability extends beyond immediate financial implications, affecting the integrity, security, and long-term viability of the protocol. Addressing this issue is crucial to maintaining user trust and ensuring the successful adoption and growth of the project.

Tools Used

Manual Review

Recommendations

Reorder Logic: Move the assertion checks that ensure protocol invariants are met before the token transfer occurs. This ensures that all necessary conditions are validated before making irreversible state changes.

by ensuring this modification in the _withdraw() function of the SablierFlow.sol contract

.
.
.
.
- // Perform the ERC-20 transfer after all checks are confirmed.
- token.safeTransfer({ to: to, value: amount });
- // Protocol Invariant: the difference in total debt should be equal to the difference in the stream balance.
- assert(totalDebt - _totalDebtOf(streamId) == balance - _streams[streamId].balance);
+ // Protocol Invariant: the difference in total debt should be equal to the difference in the stream balance after the transfer.
+ assert(totalDebt - _totalDebtOf(streamId) == balance - _streams[streamId].balance);
+
+ // Perform the ERC-20 transfer after all checks are confirmed.
+ token.safeTransfer({ to: to, value: amount });
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.