# `EEVM.Database`
[🔗](https://github.com/mw2000/eevm/blob/main/lib/eevm/database.ex#L1)

Behaviour defining the external state interface for the EVM — account
state (balances, nonces, code) plus per-contract storage — abstracted
behind a single interface so different backends (in-memory, Merkle-backed,
disk) can be plugged in without changing opcode implementations.

A database value is a `%EEVM.Database{}` struct containing:

- `impl` — the module implementing `@behaviour EEVM.Database`
- `state` — the implementation-specific state (opaque to callers)

All public functions in this module dispatch to the `impl` module, passing
and receiving the opaque `state`. The default implementation is
`EEVM.Database.InMemory`.

# `account`

```elixir
@type account() :: %{
  optional(:balance) =&gt; non_neg_integer(),
  optional(:nonce) =&gt; non_neg_integer(),
  optional(:code) =&gt; binary(),
  optional(:storage) =&gt; EEVM.Storage.t()
}
```

# `t`

```elixir
@type t() :: %EEVM.Database{impl: module(), state: term()}
```

# `account_addresses`

```elixir
@callback account_addresses(state :: term()) :: [non_neg_integer()]
```

Return all known account addresses in the backend state.

# `account_empty?`

```elixir
@callback account_empty?(state :: term(), address :: non_neg_integer()) :: boolean()
```

Return whether account at `address` is EIP-161 empty.

# `account_exists?`

```elixir
@callback account_exists?(state :: term(), address :: non_neg_integer()) :: boolean()
```

Check whether an account exists at the given address.

# `delete_account`

```elixir
@callback delete_account(state :: term(), address :: non_neg_integer()) :: term()
```

Remove an account entirely (used by SELFDESTRUCT under EIP-6780).

# `get_account`

```elixir
@callback get_account(state :: term(), address :: non_neg_integer()) :: account() | nil
```

Fetch the full account record, or nil if the address has no state.

# `get_balance`

```elixir
@callback get_balance(state :: term(), address :: non_neg_integer()) :: non_neg_integer()
```

Return the balance in wei for `address` (0 if non-existent).

# `get_code`

```elixir
@callback get_code(state :: term(), address :: non_neg_integer()) :: binary()
```

Return the bytecode deployed at `address` (empty binary if none).

# `get_nonce`

```elixir
@callback get_nonce(state :: term(), address :: non_neg_integer()) :: non_neg_integer()
```

Return the nonce for `address` (0 if non-existent).

# `increment_nonce`

```elixir
@callback increment_nonce(state :: term(), address :: non_neg_integer()) :: term()
```

Increment the nonce at `address` by 1.

# `put_account`

```elixir
@callback put_account(state :: term(), address :: non_neg_integer(), account :: account()) ::
  term()
```

Replace the entire account record at `address`.

# `put_code`

```elixir
@callback put_code(state :: term(), address :: non_neg_integer(), code :: binary()) ::
  term()
```

Set the bytecode at `address`.

# `set_balance`

```elixir
@callback set_balance(
  state :: term(),
  address :: non_neg_integer(),
  balance :: non_neg_integer()
) :: term()
```

Set the balance at `address`.

# `set_nonce`

```elixir
@callback set_nonce(
  state :: term(),
  address :: non_neg_integer(),
  nonce :: non_neg_integer()
) :: term()
```

Set the nonce at `address`.

# `storage_addresses`

```elixir
@callback storage_addresses(state :: term()) :: [non_neg_integer()]
```

Return addresses that currently have tracked storage entries.

# `storage_load`

```elixir
@callback storage_load(
  state :: term(),
  address :: non_neg_integer(),
  key :: non_neg_integer()
) :: non_neg_integer()
```

Load a 256-bit storage slot for the given contract address.

# `storage_slots`

```elixir
@callback storage_slots(state :: term(), address :: non_neg_integer()) :: [
  {non_neg_integer(), non_neg_integer()}
]
```

Return all storage slots currently tracked for an address.

# `storage_store`

```elixir
@callback storage_store(
  state :: term(),
  address :: non_neg_integer(),
  key :: non_neg_integer(),
  value :: non_neg_integer()
) :: term()
```

Store a 256-bit value into a storage slot for the given contract address.

# `transfer`

```elixir
@callback transfer(
  state :: term(),
  from :: non_neg_integer(),
  to :: non_neg_integer(),
  amount :: non_neg_integer()
) :: {:ok, term()} | {:error, :insufficient_balance}
```

Transfer `amount` wei from one address to another.

# `account_addresses`

```elixir
@spec account_addresses(t()) :: [non_neg_integer()]
```

# `account_empty?`

```elixir
@spec account_empty?(t(), non_neg_integer()) :: boolean()
```

# `account_exists?`

```elixir
@spec account_exists?(t(), non_neg_integer()) :: boolean()
```

# `delete_account`

```elixir
@spec delete_account(t(), non_neg_integer()) :: t()
```

# `get_account`

```elixir
@spec get_account(t(), non_neg_integer()) :: account() | nil
```

# `get_balance`

```elixir
@spec get_balance(t(), non_neg_integer()) :: non_neg_integer()
```

# `get_code`

```elixir
@spec get_code(t(), non_neg_integer()) :: binary()
```

# `get_nonce`

```elixir
@spec get_nonce(t(), non_neg_integer()) :: non_neg_integer()
```

# `increment_nonce`

```elixir
@spec increment_nonce(t(), non_neg_integer()) :: t()
```

# `new`

```elixir
@spec new(module(), term()) :: t()
```

Wraps an implementation module and its initial state into a `%Database{}`.

## Example

    db = Database.new(Database.InMemory, Database.InMemory.init())

# `put_account`

```elixir
@spec put_account(t(), non_neg_integer(), account()) :: t()
```

# `put_code`

```elixir
@spec put_code(t(), non_neg_integer(), binary()) :: t()
```

# `set_balance`

```elixir
@spec set_balance(t(), non_neg_integer(), non_neg_integer()) :: t()
```

# `set_nonce`

```elixir
@spec set_nonce(t(), non_neg_integer(), non_neg_integer()) :: t()
```

# `storage_addresses`

```elixir
@spec storage_addresses(t()) :: [non_neg_integer()]
```

# `storage_load`

```elixir
@spec storage_load(t(), non_neg_integer(), non_neg_integer()) :: non_neg_integer()
```

# `storage_slots`

```elixir
@spec storage_slots(t(), non_neg_integer()) :: [
  {non_neg_integer(), non_neg_integer()}
]
```

# `storage_store`

```elixir
@spec storage_store(t(), non_neg_integer(), non_neg_integer(), non_neg_integer()) ::
  t()
```

# `transfer`

```elixir
@spec transfer(t(), non_neg_integer(), non_neg_integer(), non_neg_integer()) ::
  {:ok, t()} | {:error, :insufficient_balance}
```

---

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