# Gas Griefing Attack

Consensys Diligence has acknowledged the issue ([SWC-126](https://swcregistry.io/docs/SWC-126)) from previously section in their documentation, indicating a potential problem. However, they have not provided a suitable solution to address the issue, which suggests a misunderstanding of the problem at hand. Their attempts to propose a resolution have fallen short in effectively resolving the issue.

```solidity
contract Caller {
    function execute(address to, bytes calldata data, uint256 gas) external {
        require(gasleft() >= gas);
        (bool success, bytes memory returnedData) = to.call.gas(gas)(data);
        // Handle the result of the call
    }
}
```

Imagine you have a smart contract that uses the `require` statement to perform a call to another contract using the `to.call` function. You want to make sure that the ***callee*** contract receives a specific amount of gas that you specify.

However, there are two reasons why the `require` call alone cannot guarantee this:

* Gas required for the call itself: When you make the call, the gas required for the call's operations and memory usage will further reduce the available gas. This means that the actual gas available at the moment of the call will be lower than what you initially expected.
* The 63/64 rule: Even if the gas available at the point of the call seems sufficient, the Ethereum protocol applies the 63/64 rule. This rule reduces the available gas even more, potentially affecting the amount of gas the ***callee*** contract receives. The remaining gas (1/64 of the gas required) can still be enough for the rest of the transaction to succeed, allowing the call to continue.

## Relayers and Gas Manipulation: Understanding the Vulnerabilities

Now, let's consider a meta-transaction scenario. In meta-transactions, a relayer signs and submits transactions on behalf of users. Here's where the issue arises: a malicious or unaware relayer could sign a transaction with a low amount of gas, intentionally or unintentionally causing the inner call to fail. However, they would still set the overall transaction up for success by providing enough gas for the transaction itself. In this scenario, the relayer would be rewarded for executing the transaction, while the user would experience a failed meta-transaction.

Furthermore, if a relayer manages to make the first meta-transaction fail, it could impact the entire series of meta-transactions generated by the user.

To address this issue, there is a need for a mechanism that ensures smart contracts can reliably guarantee that the ***callee*** contract receives the exact amount of gas specified, regardless of the gas reductions caused by the call and the 63/64 rule.

## Mitigating Gas Griefing Attack

To properly guard against the issue, we need to ensure there is enough gas at the point of the call being made.\
\
There are two ways to achieve this within the current EVM framework:

### First Solution

Check before the call:

```solidity
uint256 gasAvailable = gasleft() - E;
require(gasAvailable - gasAvailable / 64  >= txGas, "not enough gas provided")
to.call.gas(txGas)(data); 
```

In this approach, we calculate the available gas by subtracting the gas used in the operations preceding the call (E) from the current gas available `gasleft()`. We then compare this value with the required gas for the call `txGas` minus 1/64 of the available gas. If the comparison fails, indicating insufficient gas, the call is not made. This method relies on estimating the gas required for the operations preceding the call and the call itself, which is opcode pricing dependent.

### Second Solution

Check after the call:

```solidity
to.call.gas(txGas)(data);
assert(gasleft() > txGas / 63, "not enough gas left");
```

Here, we make the call first using the specified gas `txGas`, and then we assert that the gas remaining after the call is greater than `txGas` divided by 63. If the remaining gas is not sufficient, the assertion fails, causing the current call to revert. This workaround does not require estimating the gas required for the preceding operations and is not dependent on specific opcode pricing.

## Potential Pitfalls of the Second Approach

It's important to note that the second approach may still pass the check if the gas provided was less, and the external call reverted or succeeded early, leaving enough gas remaining. This can be problematic if the code executed during the call reverts due to a check against the gas provided. To address this, an `assert` statement is used to consume all gas, emulating an out-of-gas exception. However, it's worth mentioning that the `assert` statement may not consume all gas in newer versions of Solidity (>= 0.8.0), requiring the use of assembly to emit an invalid opcode.

However, these workarounds have limitations, and a proper solution would involve making changes to the EVM itself to ensure reliable gas allocation for callee contracts.
