Flow

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

Potential for Contract Self-Destruction via Delegatecall

Summary

The Batch contract, which facilitates batched calls to functions within the same contract using delegatecall. The use of delegatecall introduces a significant vulnerability risk, as it can allow malicious calls to execute selfdestruct, leading to potential contract termination and loss of assets.

Vulnerability Details

The batch function in the Batch contract allows multiple function calls to be executed in a single transaction. However, the use of delegatecall means that any function can manipulate the state of the contract. Specifically, if a caller passes a payload to a function that includes selfdestruct, the contract could be destroyed.

By passing a specific payload, a malicious actor could trigger selfdestruct, which would irreversibly remove the contract from the blockchain, along with any associated funds or state.

Impact

A malicious actor could destroy the contract, leading to a total loss of funds and functionality.

Tools Used

Manual Code Review

Recommendations

Avoid delegatecall for User-Facing Functions: Refrain from using delegatecall for functions that can be called by users. Consider alternatives such as directly calling the target functions.

OR

Add logic which checks whether selfdestruct is being called by an attacker and it's then throw and error, it should look something like this:

abstract contract Batch {
bytes4 private constant SELF_DESTRUCT_SIGNATURE = bytes4(keccak256("selfdestruct(address)"));
function batch(bytes[] calldata calls) external {
uint256 count = calls.length;
for (uint256 i = 0; i < count; ++i) {
if (isSelfDestructCall(calls[i])) {
revert("Selfdestruct is not allowed");
}
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
if (!success) {
revert Errors.BatchError(result);
}
}
}
function isSelfDestructCall(bytes memory callData) internal pure returns (bool) {
// Check if the first 4 bytes of callData match the selfdestruct signature
return (callData.length >= 4 && bytes4(callData) == SELF_DESTRUCT_SIGNATURE);
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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