With no gas limit, the chances are:
Increased Gas Costs: Without a limit, a call may consume unexpectedly high gas, which could deplete the caller’s funds or affect the gas efficiency of the overall system.
Denial of Service (DoS): If excessive gas consumption exhausts the sender’s balance or exceeds the gas stipend, subsequent operations or other contract interactions may fail, causing potential DoS issues within the contract's flow.
There are other possibilities, however low, but still there.
The lack of gas control can become a high vulnerability, particularly when combined with reentrancy risks or untrusted external calls:
Reentrancy Attacks: If the external call is to a contract that might reenter and manipulate the calling contract’s state, setting a gas limit is critical. Unrestricted gas allows malicious contracts to perform multiple actions, which can exploit reentrancy vulnerabilities and potentially drain funds or manipulate contract state.
Untrusted Contract Interactions: When the external call involves interactions with unknown or potentially malicious contracts, unrestricted gas opens up the possibility for complex and unpredictable contract behaviors. An untrusted contract could craft a complex call sequence to drain resources or interfere with contract logic.
Unexpected Failures: Lack of a gas limit can cause unexpected behavior in cases where gas usage surges unpredictably, which may interfere with critical functions and data consistency, especially in complex multi-call flows.
Description: When calling an external contract without specifying a gas limit, all available gas is forwarded to the external call by default. This can enable malicious contracts to perform complex reentrant calls that take advantage of the unbounded gas.
Exploitation:
If the external contract (contractAddress) reenters and makes a recursive call back to the original function, it may lead to repeated state changes or withdrawals, especially if state updates are performed after the external call.
In a common reentrancy attack, the malicious contract repeatedly reenters the external call, exploiting the unrestricted gas to drain the contract’s funds or manipulate state variables.
Impact: Potential loss of funds, incorrect state updates, or data corruption.
Example Scenario:
In this example, the attacker can use reentrancy to repeatedly call withdraw() before the balances[msg.sender] = 0; update, draining funds.
Description: When no gas limit is set, an external contract could consume excessive gas, potentially exhausting the caller’s available gas and causing an unexpected failure. This can lead to DoS conditions, preventing the calling function or even other functions from completing successfully.
Exploitation:
Malicious contracts or unoptimized contracts could intentionally include gas-heavy operations, such as recursive loops or highly complex computations.
Since the caller’s gas can be depleted, other users attempting to call the function or related functions may encounter failures, effectively creating a DoS scenario.
Impact: Disruption of contract functionality, transaction failures, or inability to perform critical operations.
Example Scenario:
If externalContract executes gas-heavy operations, the call might exhaust the gas provided by the caller, causing processRequest() to fail repeatedly.
Description: Gas griefing attacks exploit unlimited gas forwarding to cause unwanted high gas usage for the user or contract owner. When gas is unbounded, even a non-malicious external contract can sometimes consume more gas than expected, resulting in expensive transactions for the caller.
Exploitation:
An attacker could deploy a contract with deliberately inefficient functions, increasing gas costs when interacting with the original contract.
If users or other contracts are unable to estimate gas limits properly due to the unpredictably high gas use, they may face unnecessary expenses or fail to execute transactions.
Impact: Unintended high gas fees, potentially limiting user participation or driving up operating costs.
Example Scenario:
Here, if targetContract has a gas-heavy function, performOperation() could become cost-prohibitive for the caller due to high gas usage.
Description: When calling untrusted contracts without a gas limit, a malicious contract’s fallback function could consume an excessive amount of gas each time it’s called, either in a loop or through multiple fallback triggers.
Exploitation:
A fallback function in an attacker’s contract could drain gas through repetitive invocations or deliberately inefficient code, forcing the original function to fail or deplete resources.
Since fallback functions can be designed to handle arbitrary calls, they’re particularly risky when allowed unbounded gas, especially in interactions that require repeated or recursive calls.
Impact: Contract operation failures, resource depletion, increased gas fees, or user dissatisfaction.
Example Scenario:
An attacker’s contract could have a fallback function that consumes gas heavily, causing executeTransaction to fail or incur high costs repeatedly.
Vulnerable Contract: The contract that calls an external contract without specifying a gas limit, allowing excessive gas consumption.
Gas Griefing Contract: A contract designed to exploit the vulnerable contract by executing a gas-intensive operation when called.
This contract has a function callExternal() that calls an external contract without setting a gas limit. This lack of gas restriction allows a malicious or poorly optimized contract to consume an excessive amount of gas, potentially causing the transaction to fail or incurring unexpectedly high gas costs.
This contract performs a gas-intensive operation (such as a loop) when it is called. It’s used to demonstrate the excessive gas usage vulnerability in VulnerableContract’s callExternal() function.
Setup: Deploy VulnerableContract and GasGriefingContract.
Attack:
The attacker calls VulnerableContract.callExternal() with GasGriefingContract as the target and the consumeGas() function as data.
VulnerableContract forwards an unbounded amount of gas to GasGriefingContract, which performs a gas-intensive loop in consumeGas().
Since VulnerableContract does not limit the gas, GasGriefingContract can consume an excessive amount of gas, either causing the transaction to fail due to out-of-gas errors or forcing the user to pay unnecessarily high gas fees.
Here’s how to perform the exploit by calling callExternal():
High Gas Fees: The call to consumeGas() in GasGriefingContract will consume a lot of gas, potentially causing high transaction fees for the caller.
Transaction Failure: If the gas consumption exceeds the caller’s gas limit, the transaction will fail with an out-of-gas error.
To prevent this vulnerability, the VulnerableContract should set a reasonable gas limit for external calls:
This PoC demonstrates how a lack of gas limit control in external calls can lead to gas griefing attacks, where a malicious contract can cause the caller to pay high fees or experience transaction failures. By setting a gas limit, you can prevent unbounded gas consumption, making the contract safer and more predictable in terms of gas usage.
4o
target.call{gas: 50000}(data) limits the call to 50,000 gas units.Use Reentrancy Guards: Always apply nonReentrant where external calls are made to prevent recursive exploitation.
Perform State Changes Before External Calls: Critical state updates (e.g., balances, access rights) should be completed before the external call to ensure that a reentrant call cannot manipulate the contract’s state unexpectedly.
Avoid Direct Calls to Untrusted Contracts: If possible, minimize direct interaction with contracts that are not verified or known to be trusted. Use proxy contracts or intermediaries to interact with unknown contracts.
Add Comprehensive Logging: Include events for successful and failed calls to monitor suspicious activities, which can help detect early signs of gas-based abuse or unusual external interactions.
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.