Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

External call made in `MembershipFactory` contract does not include gas limit making it vulnerable to gas griefing attack

Summary

The EXTERNAL_CALLER role is allowed to call an arbitrary contract through the MembershipFactory::callExternalContract function. However, the external call does not include gasLimit parameter. This makes the EXTERNAL_CALLER transactions vulnerable to gas griefing attack resulting in DoS.

Vulnerability Details

The EXTERNAL_CALLER role is allowed to call an arbitrary contract through the MembershipFactory::callExternalContract function. However, the external call does not include gasLimit parameter.

https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/MembershipFactory.sol#L177

When an external call is made to another contract without gas limit, 63/64 total gas available is forwarded to the called contract for execution of the call and it is expected to refund unused gas. If the called contract exhaust or consume a substantial amount of this gas in the process of execution, then there will not be sufficient gas left to perform the remaining calls within the transaction, especially when there are multiple contract calls included within this transaction. This transaction will fail because of insufficient gas. Even if the transaction gets executed completely unnecessary gas will be spent by the called contract making the transaction more expensive. This can easily be mitigated by specifying gas limit during the call.

Interacting with a poorly written function within a contract or a malicious contract causes this denial of service through gas griefing.

Impact

Denial of service to the EXTERNAL_CALLER role calling MembershipFactory::callExternalContract function as one of multiple contract calls within a transaction.

Tools Used

Manual review

Recommendations

Include user-defined gasLimit in the external call and use try-and-catch block to handle failure or reverts.

function callExternalContract(
address contractAddress,
+ uint256 gasLimit,
bytes memory data
) external payable onlyRole(EXTERNAL_CALLER) returns (bytes memory) {
(bool success, bytes memory returndata) = contractAddress.call{
value: msg.value,
+ gas : gasLimit
}(data);
require(success, "External call failed");
return returndata;
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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