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

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

- **Charge upfront** — check that the sender can afford the maximum fee,
  then debit `gas_limit * effective_price` 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 `effective_gas_price/2`, which `PostExecution` settlement
shares, 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.TxEnv.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.TxEnv.t(), EEVM.BlockEnv.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.TxEnv.new(type: :eip4844, blob_hashes: [1, 2])
    iex> EEVM.Handler.PreExecution.blob_gas_fee(tx, EEVM.BlockEnv.new(blob_base_fee: 3))
    786_432

# `charge_upfront`

```elixir
@spec charge_upfront(
  EEVM.Database.t(),
  EEVM.TxEnv.t(),
  EEVM.BlockEnv.t(),
  EEVM.Config.t()
) ::
  {:ok, EEVM.Database.t()} | {:error, atom()}
```

Debit `gas_limit * effective_gas_price` and the blob gas fee from the
sender, after checking that the effective gas price meets the basefee and
that the balance covers the maximum fee plus `tx.value`.

The maximum fee prices gas at `max_fee_per_gas` (EIP-1559) and blob gas at
`max_fee_per_blob_gas` (EIP-4844), but only the effective fee is debited,
so BALANCE of the sender during execution already excludes the unspent
fee cap (execution-specs `process_transaction`).

`config`'s `disable_balance_check` and `disable_base_fee` simulation
switches skip the matching check. With the balance check off, the sender
keeps at least `tx.value` and pays the gas charge only as far as its
balance allows, as revm's `CfgEnv` does.

# `effective_gas_price`

```elixir
@spec effective_gas_price(EEVM.TxEnv.t(), EEVM.BlockEnv.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.

# `initial_accessed_addresses`

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

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

# `initial_accessed_storage_keys`

```elixir
@spec initial_accessed_storage_keys(EEVM.TxEnv.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.TxEnv.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*
