Skip to main content
Sigvex

Gas Griefing Remediation

Reserve a gas minimum, forward a bounded amount, and require inner call success so callers cannot starve nested calls.

Gas Griefing Remediation

Overview

Gas griefing lets an attacker supply just enough gas for the outer function to finish while starving a nested external call. If the outer function ignores the inner call’s result, the inner operation silently fails while side effects (fee collection, counter increments) still run. This is most damaging in relayers, meta-transactions, and batch operations where the caller controls the gas budget.

Related Detector: Gas Griefing

Before (Vulnerable)

function relay(address target, bytes calldata data) external {
    target.call(data);  // May fail due to insufficient gas
    relayerRewards[msg.sender] += fee;
}

After (Fixed)

function relay(address target, bytes calldata data) external {
    require(gasleft() >= MIN_GAS_RESERVE + 50000, "Insufficient gas");
    (bool success, ) = target.call{gas: gasleft() - MIN_GAS_RESERVE}(data);
    require(success, "Inner call failed");
    relayerRewards[msg.sender] += fee;
}

The gas check ensures the transaction was supplied enough headroom for the inner call to run, the bounded forwarding leaves a reserve for the outer logic to complete, and the success requirement reverts the whole transaction if the inner call fails. The attacker can no longer make the call appear to succeed while the nested operation is starved.

Alternative Mitigations

  • Require a specific minimum gasleft() at the entry point and document it so relayers can size their gas correctly.
  • For batch operations, give each item an explicit per-item gas allocation and revert the batch if any item runs out.
  • Where best-effort behavior is intentional, record the inner call’s success or failure on-chain so downstream accounting can react.

Common Mistakes

  • Checking the boolean return value but still crediting fees before the check, so griefed calls are paid for.
  • Forwarding gasleft() with no reserve, leaving nothing for the post-call logic and reintroducing the failure window.
  • Setting MIN_GAS_RESERVE too low for the actual cost of the trailing state writes.

References