Flow

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

Unrestricted Batch Call Execution Leading to Potential Denial-of-Service (DoS)

Summary

The Batch contract allows users to execute multiple function calls in a single transaction without any restriction on the number of calls. This lack of limitation can be exploited to perform a Denial-of-Service (DoS) attack, where an attacker can submit an excessively large batch of calls, causing the contract to become unresponsive and disrupting service for legitimate users.

Vulnerability Details

The vulnerability arises from the absence of a limit on the number of calls that can be processed in a single batch.

function batch(bytes[] calldata calls) external {
@=> uint256 count = calls.length;
@=> for (uint256 i = 0; i < count; ++i) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
if (!success) {
revert Errors.BatchError(result);
}
}
}

The batch function processes all calls in the calls array without any checks on the array's length.

Scenario:

  1. An attacker crafts a batch containing thousands of function calls.

  2. The attacker submits this batch to the Batch contract.

  3. The contract attempts to process each call, consuming significant computational resources.

  4. As a result, the contract becomes unresponsive, delaying or preventing legitimate transactions from being processed.

Impact

  • The contract may become unresponsive, delaying or blocking legitimate transactions.

  • Continuous submission of large batches can exhaust computational resources, affecting the contract's performance and availability.

Tools Used

Manual review

Recommendations

Implement a limit on the number of calls that can be processed in a single batch.

function batch(bytes[] calldata calls) external {
uint256 count = calls.length;
// Limit the number of calls in a batch to a reasonable number, e.g., 10
+ require(count <= 10, "Batch call limit exceeded");
for (uint256 i = 0; i < count; ++i) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
if (!success) {
revert Errors.BatchError(result);
}
}
}
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.