Flow

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

Integer Overflow in Aggregate Balance

Summary

Integer Overflow in Aggregate Balance

Vulnerability Details

function collectProtocolRevenue(IERC20 token, address to) external override onlyAdmin {
uint128 revenue = protocolRevenue[token];
// Check: there is protocol revenue to collect.
if (revenue == 0) {
revert Errors.SablierFlowBase_NoProtocolRevenue(address(token));
}
// Effect: reset the protocol revenue.
protocolRevenue[token] = 0;
unchecked {
// Effect: update the aggregate balance.
aggregateBalance[token] -= revenue;
}
// Interaction: transfer the protocol revenue to the provided address.
token.safeTransfer({ to: to, value: revenue });
emit ISablierFlowBase.CollectProtocolRevenue({ admin: msg.sender, token: token, to: to, revenue: revenue });
}

unchecked {````aggregateBalance[token] -= revenue;````}

The subtraction occurs in an unchecked block

  • No verification that aggregateBalance[token] >= revenue

  • Can lead to underflow, causing the balance to wrap around to a very large number

`// Initial State

aggregateBalance = 1000 USDC

protocolRevenue = 0 USDC

// Step 1: Create Large Stream
amount = 10000 USDC

fee = 100 USDC (1% fee)

new aggregateBalance = 1100 USDC

protocolRevenue = 100 USDC

// Step 2: Cancel Stream Immediately

returned = 9900 USDC

aggregateBalance = 1100 USDC

protocolRevenue = 100 USDC

// Step 3: Withdraw Most Tokens

withdraw(9900 USDC)

aggregateBalance = 1100 USDC

actual balance = 100 USDC

protocolRevenue = 100 USDC

// Step 4: Repeat Process

// After several iterations:

aggregateBalance = 1100 USDC

actual balance = 100 USDC

protocolRevenue = 1500 USDC // Now greater than aggregateBalance!`

// Starting state

Contract balance: 1000 USDC

Aggregate balance tracked: 1000 USDC

Protocol revenue: 1500 USDC

// Attack sequence

  1. Admin calls collectProtocolRevenue()

  2. Contract tries: 1000 - 1500

  3. Instead of failing, it underflows to: 2^256 - 500

  4. Now contract thinks it has massive balance!

// Effect on other functions:

function recover(IERC20 token, address to) external {

// This calculation becomes wildly wrong after overflow

uint256 surplus = token.balanceOf(address(this)) - aggregateBalance[token];

// If aggregateBalance is huge, surplus calculation underflows

// Making recovery impossible````}

Impact

Protocol revenue collection could underflow aggregate balance. Contract's accounting system becomes corrupted. Could lead to token theft through recover() function

Tools Used

Manual Review

Recommendations

Using Safe arithmetic prevents underflow/overflow. Add tracking for total deposits and withdrawals

Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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