Flow

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

Risk of Out-of-Gas Errors in Batched Calls

Summary

The batch function in the Batch contract lacks a limit on the number of batched calls, which can lead to out-of-gas errors during execution. This poses a risk for unexpected transaction failures.

Finding Description

The batch function allows users to execute multiple function calls in a single transaction via delegatecall. However, if the calls array exceeds a certain size, the total gas consumed during execution can exceed the block gas limit or the gas limit set by the user. This results in the entire transaction failing, leading to a poor user experience and potentially leaving the contract in an inconsistent state.

The security guarantee that is broken here is availability. Users may be unable to execute their intended operations if the gas limit is exceeded. A malicious user could exploit this by submitting a batch with an excessive number of calls, causing gas exhaustion intentionally.

Vulnerability Details

  • Location: The vulnerability exists within the batch function of the Batch contract.

  • Propagation: If a user submits a large number of calls in the calls array, the function will attempt to process them all without any check on the number of calls. This can lead to an out-of-gas condition, resulting in the transaction reverting without executing any of the calls.

Impact

The inability to process a large number of calls in one transaction could lead to failed transactions, causing user frustration and potential loss of funds if the calls involve state changes. The overall user experience would be severely impacted, as they might assume that the function works correctly without understanding the underlying gas constraints.

Proof of Concept

A user could create a transaction with the following call:

bytes[] memory calls = new bytes[](); // Example of creating 101 calls
// Populate calls with data for function calls
contractInstance.batch(calls);

If this transaction is sent, it could exceed the gas limit and cause the transaction to fail.

Recommendations

To mitigate this issue, the contract should implement a maximum limit on the number of calls allowed in a single transaction. For example, limiting the number of calls to 100 ensures that users cannot submit excessively large arrays that could lead to gas exhaustion.

Here's a suggested code snippet to enforce this limit:

function batch(bytes[] calldata calls) external {
uint256 count = calls.length;
require(count > 0, "No calls provided"); // Check for empty input
require(count <= 100, "Too many calls"); // Limit on the number of calls
for (uint256 i = 0; i < count; ++i) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
if (!success) {
revert Errors.BatchError(result.length > 0 ? result : "Unknown error");
}
}
emit BatchExecuted(count); // Event emission for logging
}

File Location

src/abstracts/Batch.sol

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.