The use of delegatecall in the batch function creates a potential reentrancy vulnerability, allowing malicious contracts to exploit the state of the Batch contract.
The batch function uses delegatecall to execute arbitrary functions specified in the calls array. Since delegatecall executes the called function in the context of the Batch contract, any state changes made by the called function can affect the Batch contract's state.
A malicious contract could be designed to call a function that modifies its own state, which, if executed within the batch function, could lead to unexpected behavior or state corruption. For example, an attacker could manipulate state variables in the Batch contract or perform actions that they shouldn't be allowed to.
This vulnerability breaks the security guarantees of:
Reentrancy Protection: By allowing an external contract to execute code within the context of the Batch contract, it undermines the integrity of state management.
Controlled Execution Flow: The contract cannot guarantee that state is safe to modify when external calls are executed.
The risk arises from the combination of delegatecall and user-supplied input. If an attacker crafts a malicious payload that modifies the contract's state, they can exploit this reentrancy vulnerability to perform unauthorized actions or extract funds.
A malicious contract could send a payload that triggers a function which calls back into the batch function before the state has been finalized, allowing it to bypass checks or double-spend funds.
The impact of this vulnerability could be severe, potentially leading to loss of funds, unauthorized access to contract functions, or corruption of the contract’s state. Given the nature of delegatecall, the attacker can manipulate the execution flow and potentially steal funds or disrupt normal contract operations.
Here’s a simple proof of concept demonstrating the reentrancy risk:
Create a malicious contract that invokes a function in the Batch contract.
Within that function, call the batch function again before the initial call completes.
To mitigate the reentrancy risk, implement a reentrancy guard pattern in the batch function. This can be achieved using a simple boolean flag or using the OpenZeppelin ReentrancyGuard library.
Using the nonReentrant modifier from OpenZeppelin will help prevent reentrant calls and protect the contract's state.
src/abstracts/Batch.sol
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.