> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://www.getfoundry.sh/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

## `lastFrameGas`

### Signatures

```solidity
struct Gas {
    uint64 gasLimit;
    uint64 gasTotalUsed;
    uint64 gasMemoryUsed;
    int64 gasRefunded;
    uint64 gasRemaining;
    int64 gasStateUsed;
}

function lastFrameGas() external view returns (Gas memory gas);
function lastCallGas() external view returns (Gas memory gas);
```

### Description

`lastFrameGas` returns gas measurements for the most recently completed external call or contract creation. The values are recorded from the callee's perspective, so they describe the child execution frame rather than all overhead paid by its caller.

### Comparison with `lastCallGas`

`lastFrameGas` extends `lastCallGas` with **contract creation** (`CREATE` and `CREATE2`); it is more than a rename. Both return the same `Gas` struct and use the same gas accounting for a given call. `lastCallGas` only records calls and is deprecated; use `lastFrameGas` for new tests.

| Most recently completed operation | `lastFrameGas()` | `lastCallGas()` |
| --- | --- | --- |
| An external call | Gas for that call | The same gas measurements for that call |
| Contract creation whose constructor makes no external calls | Gas for the creation frame | Gas for the earlier call, or reverts if no call has been recorded |
| Contract creation whose constructor makes external calls | Gas for the completed creation frame, including nested execution | Gas for the most recently completed call within the constructor |

For example, after `target.setValue(42)` followed by `new GasTarget()` with no external calls in its constructor, `lastFrameGas()` describes the creation while `lastCallGas()` still describes `setValue`. Replacing `lastCallGas` with `lastFrameGas` therefore changes what you measure if a creation completes between the call you intended to measure and the measurement.

Reading either value does not replace the recorded frame because cheatcode calls are excluded from this measurement.

### Returns

| Field | Type | Description |
|-------|------|-------------|
| `gasLimit` | `uint64` | Regular gas limit of the frame. Excludes the EIP-8037 state gas reservoir; it is not the transaction's combined limit or the minimum required to succeed. |
| `gasTotalUsed` | `uint64` | Regular (execution) gas used, including nested execution, before subtracting `gasRefunded`. **Excludes EIP-8037 state gas.** With isolation, includes intrinsic gas and the regular-gas calldata floor. Without EIP-8037, state creation costs use the ordinary gas schedule and are included here. |
| `gasMemoryUsed` | `uint64` | Deprecated; always `0`. Memory expansion costs are included in `gasTotalUsed`. |
| `gasRefunded` | `int64` | Ordinary gas refund counter for the frame, which can be negative in a nested frame. Without isolation, this is before the transaction-wide refund cap and calldata floor. With isolation, this is the isolated transaction's final refund reported by the EVM. **Excludes state gas refills**, which are already reflected in `gasStateUsed`. Refunds do not provide gas to continue executing. |
| `gasRemaining` | `uint64` | Regular gas remaining at completion. **Excludes the state gas reservoir.** State charges can draw from regular gas and state refills can restore it, so `gasLimit - gasRemaining` need not equal `gasTotalUsed`. |
| `gasStateUsed` | `int64` | Net EIP-8037 state creation gas, including nested execution, **excluding regular gas** and already subtracting state refills. Zero without EIP-8037 and for reverted or halted frames. Can be negative when a successful nested frame undoes state creation charged by an earlier frame in the same transaction. Do not subtract `gasRefunded` from this value. |

### Regular gas, state gas, and total gas

[Regular gas and execution gas mean the same dimension](/forge/gas-accounting): computation, memory, access costs, and transaction intrinsic costs. [EIP-8037](https://eips.ethereum.org/EIPS/eip-8037) adds a separate **state gas** dimension for state creation, such as new storage slots, accounts, and deployed code. Reading or updating existing state still costs regular gas.

When EIP-8037 is active, `gasTotalUsed` excludes state gas regardless of whether the state charge was paid from the reservoir or spilled into regular gas. An exceptional halt consumes the remaining regular allowance after state rollback; those consumed units are reported as regular gas and `gasStateUsed` is zero.

For the net sum of the measured components, widen both fields to signed integers before adding them. The example below disables isolation so both calls share one transaction: the second call undoes the first call's state creation and reports a negative state delta. With isolation enabled, the calls are separate transactions and clearing the slot reports zero state gas instead.

Use Solidity 0.8.36, `evm_version = "amsterdam"`, and `experimental = true` for this example. The [complete example project](https://github.com/foundry-rs/book/tree/master/src/snippets/projects/gas-accounting) includes these settings. From that directory, install a current forge-std containing `gasStateUsed` and run:

```bash
$ forge install foundry-rs/forge-std --no-git
$ forge test --match-contract StateGasTest -vv
```

The function's inline configuration disables isolation only for this test:

```solidity [test/StateGas.t.sol]
// [!include ~/snippets/projects/gas-accounting/test/StateGas.t.sol:components]
```

That sum is **not a gas-limit estimate**. You may need gas temporarily before a state refill, and the caller pays additional overhead. Call forwarding rules and the regular gas cap also constrain execution. A negative state delta is valid accounting, not a negative gas limit.

Use the transaction receipt's `gasUsed` for the total charged by a mined transaction. It already includes regular and state gas, refunds, and the calldata floor. Do not add state gas again. Use `eth_estimateGas` on a node supporting the target network's rules to estimate the transaction gas limit. See [which gas value to use](/forge/gas-accounting#which-value-should-you-use).

### Isolation and network support

With isolation enabled, a top-level external call or creation in a test runs as a separate transaction. Its measurement includes transaction intrinsic gas, and `gasTotalUsed` uses the transaction's regular block-accounting contribution, including its calldata floor. The refund field is finalized for that isolated transaction. Without isolation, these are frame-local measurements: intrinsic gas and the caller's call setup are outside the frame, and the ordinary refund counter has not been finalized. Nested frames remain frame-local even within an isolated transaction.

Do not reconstruct a receipt by blindly subtracting `gasRefunded` from the sum: frame scope, final refund handling, the calldata floor, and state charges incurred outside the child frame can differ. In particular, the isolated creation frame need not include an account-creation charge already paid by its caller.

EIP-8037 behavior depends on the selected EVM/network rules. In Foundry's Ethereum EVM, it is enabled for `amsterdam` and later EVM versions. This does not mean every live Ethereum-compatible network has activated it. On an earlier fork or a network without EIP-8037, `gasStateUsed` is zero and state creation is still charged through the ordinary gas schedule in `gasTotalUsed`. See [network support](/forge/gas-accounting#which-networks-are-affected).

### Examples

#### Inspect an external call

```solidity [test/LastFrameGas.t.sol]
// [!include ~/snippets/projects/cheatcodes/test/LastFrameGas.t.sol:call]
```

#### Inspect contract creation

```solidity [test/LastFrameGas.t.sol]
// [!include ~/snippets/projects/cheatcodes/test/LastFrameGas.t.sol:create]
```

### Gotchas

* `lastFrameGas` reverts when no external call or contract creation has completed yet.
* `lastCallGas` reverts when no external call has completed, even if a contract was created.
* The measurement is for the callee frame. It does not equal the caller's complete gas delta around the call.
* Expected-revert handling can clear the cached frame. Do not rely on `lastFrameGas` after a call or creation consumed by `vm.expectRevert`.
* Gas depends on EVM version, optimizer settings, isolation, and warm or cold state. Keep those inputs stable when comparing values.

### Related Cheatcodes

* [`snapshotGas`](/reference/cheatcodes/gas-snapshots) - Persist the last frame's gas usage or measure a code section
* [`pauseGasMetering`](/reference/cheatcodes/pause-gas-metering) - Exclude code from gas metering
* [Forge testing](/forge/testing) - Understand isolation and transaction-like call boundaries
