# `EEVM.Gas.Access`
[🔗](https://github.com/mw2000/eevm/blob/v0.1.0/lib/eevm/gas/access.ex#L1)

Cold/warm storage access cost tracking per EIP-2929.

EIP-2929 introduced the concept of "access lists" — sets of addresses and storage
keys that have already been touched during the current transaction. The first access
to an address or storage slot is "cold" (expensive), and subsequent accesses are
"warm" (cheap).

## Cost Schedule (EIP-2929)

| Access Type | Cold Cost | Warm Cost |
|-------------|-----------|-----------|
| Account (BALANCE, EXTCODESIZE, etc.) | 2,600 | 100 |
| Account (CALL family, on top of its static 100) | +2,500 | +0 |
| Storage slot (SLOAD) | 2,100 | 100 |
| Storage slot (SSTORE, on top of its schedule) | +2,100 | +0 |

This module tracks which addresses and storage keys have been accessed and returns
the appropriate cost. The state's `accessed_addresses` and `accessed_storage_keys`
MapSets are updated on each cold access.

Before Berlin there is no warm/cold distinction: the opcodes' flat static
costs (`EEVM.Gas.Static.static_cost/2`) cover the access, so these functions
charge nothing.

## References

- [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929)

# `address_access_cost`

```elixir
@spec address_access_cost(EEVM.Interpreter.MachineState.t(), non_neg_integer()) ::
  {non_neg_integer(), EEVM.Interpreter.MachineState.t()}
```

Access cost of an account-reading opcode (BALANCE, EXTCODESIZE,
EXTCODECOPY, EXTCODEHASH), whose static cost is 0 from Berlin on:
2,600 cold, 100 warm. Marks `address` warm.

# `call_access_cost`

```elixir
@spec call_access_cost(EEVM.Interpreter.MachineState.t(), non_neg_integer()) ::
  {non_neg_integer(), EEVM.Interpreter.MachineState.t()}
```

Extra access cost of a CALL-family target. Their static cost already
includes the warm price (100), so a cold target adds 2,500. Marks
`address` warm.

# `mark_address_warm`

```elixir
@spec mark_address_warm(EEVM.Interpreter.MachineState.t(), non_neg_integer()) ::
  EEVM.Interpreter.MachineState.t()
```

# `sstore_access_cost`

```elixir
@spec sstore_access_cost(
  EEVM.Interpreter.MachineState.t(),
  non_neg_integer(),
  non_neg_integer()
) ::
  {non_neg_integer(), EEVM.Interpreter.MachineState.t()}
```

Extra access cost of SSTORE: 2,100 when the slot is cold, nothing when
warm (the SSTORE schedule prices warm writes). Marks the slot warm.

# `storage_access_cost`

```elixir
@spec storage_access_cost(
  EEVM.Interpreter.MachineState.t(),
  non_neg_integer(),
  non_neg_integer()
) ::
  {non_neg_integer(), EEVM.Interpreter.MachineState.t()}
```

Access cost of SLOAD: 2,100 cold, 100 warm. Marks the slot warm.

# `warm_address?`

```elixir
@spec warm_address?(EEVM.Interpreter.MachineState.t(), non_neg_integer()) :: boolean()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
