---
description: >-
  Highlights a vulnerability related to gas allocation in contracts,
  specifically focusing on inner calls and the potential for successful attacks.
---

# Inner Call Out Of Gas Attack

There is another problem related to how gas works in Ethereum. It's possible for a contract to be attacked when it calls other contracts using almost all of the available gas (63/64 of the total gas). This attack affects inner calls where the failure of the inner call doesn't cause the calling contract to stop.

This issue is somewhat similar to a **Call Stack Depth Attack**, but there are differences. For example, calls like `<address>.send` won't fail because they still receive a minimum amount of gas called the gas stipend. The gas stipend is extra gas and is not affected by the **1/64 rule**. So, these calls always have at least 2300 gas and won't fail due to running out of gas (unless the receiving contract intentionally reverts or uses more than 2300 gas).

The issue has some similarities to the **call stack depth attack** when it's used in low-level calls that catch failures of inner calls. These types of calls may become more popular with the introduction of the `try/catch` feature in Solidity 0.6.

```solidity
contract Test {
    function test() external {
        try target.callNeeding6400000Gas() returns (string message) {
            // do something in case of success
	} catch {
            // do something else in case of failure
        }
    }
}
```

1. When a user calls the `test()` function, they can specify a gas limit for the transaction. If the gas limit is set too low (let's say 6,400,000), the inner call to `callNeeding6400000Gas()` won't receive enough gas.
2. Let's say that in case of failure, there is some code in the `catch` block that consumes 50,000 gas.
3. If the user makes a transaction with a gas limit of 6,400,000 gas and the inner call doesn't receive enough gas, it will fail with an **"out of gas"** exception.
4. As a result, the `catch` block will be executed, consuming 50,000 gas. Since we have approximately 100,000 gas available (6,400,000 / 64), the transaction will still complete successfully.

The issue here is that the _**caller**_, in this case, the `Test` contract, won't be able to know whether the failure of the inner call was due to a lack of gas or if the inner call intentionally reverted.

Therefore, caution should be exercised when using a wildcard `catch` block. It's important to be aware of this issue and carefully handle the logic inside the `try/catch` block, especially if there are cases where the _**caller**_ expects the inner call to intentionally revert.

{% hint style="info" %}
[This concern has been acknowledged by the Ethereum Foundation, and a note has been added to the Solidity documentation to raise awareness about this potential danger.](https://github.com/ethereum/solidity/commit/a3b7c73e3f864da288f3da8bacb778c69a03bce0)
{% endhint %}

## Auction Example

```solidity
contract Auction {
    ...
    ERC20Token token;
    address highestBidder;
    uint256 highestBid;
    function bid(uint256 amount) external {
        require(amount < highestBid, "higher bid required");
        address oldBidder = highestBidder;
        uint256 oldBid = highestBid;
        highestBidder = msg.sender;
        highestBid = amount;
        require(token.transferFrom(msg.sender, address(this), amount), "transfer failed");
        if (oldBidder != address(0)) {
            try token.transferFrom(address(this), oldBidder, oldBid) {
            } catch {}
        }
    }
}
```

Assuming the ERC20 token used in the code is secure and doesn't have any vulnerabilities, the code may appear safe at first glance. However, there is a potential issue with the try-catch block.

The problem arises because a new bidder can provide a specific amount of gas for the transaction. They can set it up in such a way that there isn't enough gas allocated for the second transfer call to succeed, but there is enough for the rest of the code. Since there are no significant operations after the `try-catch` block, they won't require much gas, maybe just a few hundred units.

So, let's say the `transferFrom` function requires around 20,000 gas (which is possible for an ERC20 token). If the gas provided for the transaction is such that 20,000 divided by 64 is greater than the remaining gas left for the bid call (let's say 300 gas), the `transferFrom` call will throw an **"out of gas"** exception. However, the bid call might still have enough gas to complete successfully.

This example illustrates how similar the Inner **Call Out of Gas Attack** is to the **Call Stack Depth Attack**, which was aimed to be mitigated with [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md).

In summary, even though the code may seem safe at first, the specific gas allocation in the transaction can allow for a scenario where the inner transfer call fails due to **insufficient gas**, while the rest of the code completes successfully.&#x20;
