Flow

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

Potential Exploits When `Sender == Recipient` in SablierFlow Contract

Summary

The SablierFlow contract has a potential vulnerability when the sender and recipient of a stream are the same address. This situation can lead to unintended or malicious exploitation of the protocol's debt-tracking and fund-handling mechanisms, such as circumventing debt obligations, abusing the void function to escape debts, and manipulating protocol fees.

Vulnerability Details

When the sender and recipient of a stream are identical, specific functions in the SablierFlow contract behave differently. This can lead to situations where users exploit self-streams to avoid payments, manipulate protocol fees, or abuse refunds in ways that undermine the protocol's intended behavior.

Key Exploits Identified

  1. Debt Forgiveness via Self-Voiding:

    • When sender == recipient, the user can void an insolvent stream (where the total debt exceeds the stream balance) and thereby avoid paying the full debt. This is due to the _void function forgiving any uncovered debt upon voiding an insolvent stream.

  2. Infinite Withdrawals and Redepositing:

    • If the sender and recipient are the same, the user can repeatedly withdraw and redeposit funds. This allows the user to cycle funds within the same stream without risking the loss of any funds, potentially causing an infinite loop of withdrawals and redeposits.

  3. Refund Manipulation:

    • When sender == recipient, the sender can issue refunds to themselves, effectively paying back their own funds. This allows them to initiate and terminate streams for themselves, bypassing the intended payment streaming mechanism and undermining the debt obligations.

  4. Fee Evasion:

    • With sender == recipient, the user can exploit the protocol fee structure to minimize the protocol's revenue. They might be able to manipulate the withdrawal amounts and frequency to reduce effective fees paid to the protocol.

Example

Consider a user who starts a self-stream (where sender and recipient are the same) to transfer tokens to themselves at a rate of 1 token per second.

  1. Self-Voiding to Escape Debt:

    • The user funds the stream with a partial balance of 1,000 tokens. Once they accumulate more debt than this balance (e.g., 1,500 tokens in debt), they invoke the void function. Since they control both ends of the stream, they intentionally void it, writing off the 500 tokens of uncovered debt and thereby escaping the remaining payment obligation.

  2. Infinite Withdrawals and Redepositing:

    • The user begins withdrawing tokens repeatedly, taking out funds and immediately redepositing them back into the stream. Because they control both sides, there is no real loss, allowing them to infinitely loop withdrawals and redeposits, congesting the network and exploiting the fund flow.

  3. Refunding Back to Themselves:

    • After depositing a large sum, they invoke the refund function to reclaim funds they had previously deposited. Since they are both sender and recipient, they can abuse this to cycle funds and reset the debt, undermining the protocol’s debt enforcement mechanism.

  4. Fee Evasion:

    • By carefully timing withdrawals, they can reduce the effective protocol fee. For example, they withdraw a minimal amount multiple times to reduce cumulative fees, or they use withdrawMax right before the stream depletes to minimize protocol revenue.

Impact

If exploited, these issues can lead to:

  1. Financial Loss for the Protocol: Forgiving debts, fee evasion, and refund manipulation reduce the protocol’s revenue.

  2. Integrity Risks for Debt Tracking: If users avoid debt obligations and abuse refunds, it undermines the protocol’s debt-tracking model and impacts its reliability.

  3. System Inefficiencies: Infinite withdrawal and redeposit loops increase gas usage and could congest the network, affecting other users.

Overall, the impact is Medium to High, as these behaviors compromise the financial and functional integrity of the protocol.

Tools Used

Manual Code Review: Identified logic flaws based on contextual understanding of debt handling, withdrawal, and refund mechanisms.

Scenario Testing: Evaluated potential exploits in different scenarios where sender == recipient.

Recommendations

Add a check to prevent streams where the sender and recipient are the same. This prevents the user from exploiting mechanisms that require distinct participants. Modify _create(...) function at SablierFlow.sol: 578

// Check: the sender is not the zero address.
if (sender == address(0)) {
revert Errors.SablierFlow_SenderZeroAddress();
}
// Check: sender and recipient must be different.
+ if (sender == recipient) {
+ revert("SablierFlow: Sender cannot be the recipient");
+ }
uint8 tokenDecimals = IERC20Metadata(address(token)).decimals();
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 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.