Flow

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

Timestamp Manipulation Leading to Incorrect Debt Calculation in Streaming Function

Summary

The _ongoingDebtScaledOf function in the SablierFlowBase contract calculates the ongoing debt based on the block.timestamp and the ratePerSecond. The contract assumes that the block.timestamp reflects an accurate passage of time since the last snapshot. However, due to the inherent flexibility in how blockchain miners or validators can manipulate the block.timestamp within a 15-second range, this reliance on the block.timestamp could be exploited particularly in high-rate streams where large amounts of debt accrue rapidly.

Vulnerability Details

function _ongoingDebtScaledOf(uint256 streamId) internal view returns (uint256) {
uint256 blockTimestamp = block.timestamp;
uint256 snapshotTime = _streams[streamId].snapshotTime;
uint256 ratePerSecond = _streams[streamId].ratePerSecond.unwrap();
if (ratePerSecond == 0 || blockTimestamp <= snapshotTime) {
return 0;
}
unchecked {
elapsedTime = blockTimestamp - snapshotTime;
}
return elapsedTime * ratePerSecond;
}

The _ongoingDebtScaledOf function calculates the ongoing debt accrued since the last snapshot by multiplying the elapsed time (elapsedTime) by the rate per second (ratePerSecond). The elapsedTime is derived directly from the block.timestamp which can be manipulated by miners.
A miner or validator creating a block could increase the block.timestamp by up to 15 seconds. For high-frequency streams where large amounts are transferred every second, this manipulation could lead to a significant increase in debt calculation. For example, if the ratePerSecond is 1,000 tokens per second, an additional 15 seconds would result in an extra 15,000 tokens of debt being calculated.

Consider a recipient withdrawing funds from a stream .The recipient is aware of the small window (15 seconds) miners can manipulate in block.timestamp. They coordinate with a miner to:

  • Increase the block.timestamp by 10-15 seconds at the moment of withdrawal.

  • As a result, the calculated debt increases (since elapsedTime is now artificially higher), and the recipient can withdraw more tokens than they would have under normal circumstances.

if (balance < totalDebt) {
withdrawableAmount = balance;
} else {
withdrawableAmount = totalDebt.toUint128();
}

Further, If recipient’s withdrawal succesfully frontruns the sender’s refund, the recipient can exploit this by ensuring they withdraw as much as possible before the refund reduces the available balance.

Impact

For high-rate streams, even small manipulation of block.timestamp could lead to significant financial discrepancies in debt reporting and repayment schedules.

Tools Used

Manual analysis

Recommendations

Using trusted off-chain oracles to provide accurate timestamps can help reduce the reliance on the potentially manipulated block timestamps.

Rounding the timestamp to a coarser granularity such as minutes or hours can make it harder for miners to exploit precise timestamp-dependent logic

Updates

Lead Judging Commences

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