# `EEVM.Handler.PreExecution`
[🔗](https://github.com/mw2000/eevm/blob/main/lib/eevm/handler/pre_execution.ex#L1)

Steps 4-7 of the transaction pipeline (Yellow Paper §6):

- **Charge upfront** — debit `gas_limit * max_price` from the sender, plus
  the EIP-4844 blob gas fee, which is burned and never refunded. The
  `value` portion is *not* debited here; it is moved by `Execution` when
  the call frame is set up so the same wei is not deducted twice.
- **Intrinsic gas** — verify `tx.gas_limit >= IntrinsicGas.calculate(tx, hardfork)`
  and compute the gas available to the EVM as the difference.
- **Bump nonce** — increment the sender's nonce.
- **Apply authorizations** (EIP-7702) — write delegation designators for
  each valid authorization tuple. These writes happen before execution and
  persist even if the call reverts.
- **Pre-warm access set** — seed `accessed_addresses` and
  `accessed_storage_keys` with EIP-2929 / EIP-3651 entries plus the
  transaction's access list.

Also exposes `gas_upfront/1` and `effective_gas_price/2` because both
`PostExecution` settlement and the upfront balance check share the same
fee-market formula, and `blob_gas_fee/2` for runners that settle fees
themselves.

# `authorization_outcome`

```elixir
@type authorization_outcome() :: %{
  authorities: MapSet.t(non_neg_integer()),
  refund: non_neg_integer()
}
```

Result of applying an EIP-7702 authorization list: every authority whose
signature recovered (warm for the rest of the transaction) and the gas
refund owed for authorities that already existed.

# `apply_authorizations`

```elixir
@spec apply_authorizations(
  EEVM.Database.t(),
  EEVM.Context.Transaction.t(),
  non_neg_integer()
) ::
  {EEVM.Database.t(), authorization_outcome()}
```

Apply the EIP-7702 authorization list of `tx` to `db`, after the sender's
nonce bump and before execution.

Each tuple is skipped, without failing the transaction, when its chain id
is neither 0 nor `chain_id`, its nonce is 2^64 - 1, its signature does not
recover, the authority has code other than a designator, or the
authority's nonce differs. Otherwise the authority's code becomes a
designator for `address` (or is cleared when `address` is zero) and its
nonce is incremented. Tuples apply in order, so a later tuple from the
same authority sees the earlier one's nonce bump.

# `blob_gas_fee`

```elixir
@spec blob_gas_fee(EEVM.Context.Transaction.t(), EEVM.Context.Block.t()) ::
  non_neg_integer()
```

EIP-4844 blob gas fee: `GAS_PER_BLOB * blob count * blob_base_fee`. Zero for
transactions without blobs.

## Example

    iex> tx = EEVM.Context.Transaction.new(type: :eip4844, blob_hashes: [1, 2])
    iex> EEVM.Handler.PreExecution.blob_gas_fee(tx, EEVM.Context.Block.new(blob_base_fee: 3))
    786_432

# `charge_upfront`

```elixir
@spec charge_upfront(
  EEVM.Database.t(),
  EEVM.Context.Transaction.t(),
  EEVM.Context.Block.t()
) ::
  {:ok, EEVM.Database.t()} | {:error, atom()}
```

Debit the maximum gas fee from the sender after checking that the balance
also covers `tx.value` and that the effective gas price meets the basefee.

# `effective_gas_price`

```elixir
@spec effective_gas_price(EEVM.Context.Transaction.t(), EEVM.Context.Block.t()) ::
  non_neg_integer()
```

Price per gas the sender pays: `min(max_fee, basefee + priority_fee)` for
EIP-1559-style transactions (EIP-1559), or the legacy gas price.

# `gas_upfront`

```elixir
@spec gas_upfront(EEVM.Context.Transaction.t()) :: non_neg_integer()
```

Maximum gas fee debited upfront: `gas_limit` times the fee cap (or gas price).

# `initial_accessed_addresses`

```elixir
@spec initial_accessed_addresses(
  EEVM.Context.Transaction.t(),
  EEVM.Config.t(),
  EEVM.Context.Contract.t(),
  EEVM.Context.Block.t()
) :: MapSet.t(non_neg_integer())
```

Addresses warm at transaction start (EIP-2929, EIP-2930, EIP-3651): the
callee, caller, origin, coinbase, precompiles, and access-list entries.

# `initial_accessed_storage_keys`

```elixir
@spec initial_accessed_storage_keys(EEVM.Context.Transaction.t()) ::
  MapSet.t({non_neg_integer(), non_neg_integer()})
```

Storage keys warm at transaction start: every access-list slot (EIP-2930).

# `prepare_execution`

```elixir
@spec prepare_execution(
  EEVM.Database.t(),
  EEVM.Context.Transaction.t(),
  EEVM.HardforkConfig.t()
) ::
  {:ok, EEVM.Database.t(), non_neg_integer()} | {:error, :intrinsic_gas_too_low}
```

Verify intrinsic gas, bump the sender nonce, and return the gas available
to the EVM.

---

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