> ## Documentation Index
> Fetch the complete documentation index at: https://metalayerlabs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Indexing Account Balances

# Overview

If you're building a product that indexes ETH balances on Blast, it's important that you understand how Blast's account model differs from other EVM chains.

Instead of representing ETH balances as integer values, Blast represents them in terms of **shares**. Each account has some number of shares associated with it and that number is multiplied by a **global share price** to determine its ETH balance. In this way, Blast account balances are capable of automatically rebasing as new yield is reported and the global share price increases.

For the most accurate indexing of account balances, we recommend saving individual account shares along with the global share price instead of saving account balances directly. At read time an account's balance can then be derived by multiplying its shares with the global share price.

The rest of this document describes how to accurately index every account's ETH balance on Blast using this method.

<Note>If you only need to index a small number of account balances and would prefer to avoid this custom indexing logic, you can opt out of rebasing on those accounts (see [yield modes](#yield-modes) below) and index their balances as you would normally. </Note>

# Yield Modes

Blast accounts support three different yield modes, giving the user / builder control over how they want to handle rebasing when new yield is reported:

| Yield Mode  | Description                                                              |
| ----------- | ------------------------------------------------------------------------ |
| `AUTOMATIC` | ETH balance automatically rebases (increasing only)                      |
| `VOID`      |  ETH balance never changes in response to yield; no yield is earned      |
| `CLAIMABLE` | Yield accumulates separately and can be claimed to any recipient address |

### Defaults

By default, all accounts on Blast are set to `AUTOMATIC` yield mode, which means their ETH balances will rebase automatically.

However, when a smart contract is deployed to an address, the account is switched to `VOID` mode. In practice, this means that smart contract accounts default to `VOID` mode and EOAs default to `AUTOMATIC` mode.

<Note>We say "in practice" because it is possible (but very uncommon) for ETH to be held by an account before a smart contract is deployed to it.</Note>

Both smart contracts and EOAs can change their yield modes (e.g. a smart contract opting in or an EOA opting out) using the [Blast yield predeploy](https://blastscan.io/address/0x4300000000000000000000000000000000000002) at address  `0x4300000000000000000000000000000000000002`.

See our article on [Receiving and claiming ETH Yield](/building/guides/eth-yield) for details.

## Blast's Account Model

Blast uses a modified version of `op-geth` (`blast-geth`) to represent balances in terms of shares and enable all accounts to update as yield is reported. More specifically, `blast-geth` modifies the underlying `StateAccount` struct that represents account state to accomplish this:

<CardGroup cols={2}>
  <Card title="op-geth (Upstream)">
    ```diff theme={null}

        type StateAccount struct {
            Nonce    uint64
            Root     common.Hash
            CodeHash []byte
    -       Balance  *big.Int



        }
    ```
  </Card>

  <Card title="blast-geth">
    ```diff theme={null}

        type StateAccount struct {
            Nonce     uint64
            Root      common.Hash
            CodeHash  []byte
    +       Flags     uint8
    +       Fixed     *big.Int
    +       Shares    *big.Int
    +       Remainder *big.Int
        }
    ```
  </Card>
</CardGroup>

The desired yield mode is stored in the `Flags` field  and the `Fixed`, `Shares`, and `Remainder` fields store the data required to calculate account balances in each of the three yield modes as follows:

<Tabs>
  <Tab title="AUTOMATIC">
    In `AUTOMATIC` mode, balances increase automatically as yield is reported to the L2:

    ```solidity theme={null}
    balance = account.shares * sharePrice + account.remainder
    claimable = 0
    ```

    In this mode, `account.remainder` will be a dusty value to enable wei-level precision.

    <Note>It will always be the case that `account.remainder < sharePrice` (otherwise, `account.shares` would just be higher).</Note>
  </Tab>

  <Tab title="VOID">
    In `VOID` mode, the balance remains static and no yield can be claimed:

    ```solidity theme={null}
    balance   = account.fixed
    claimable = 0
    ```
  </Tab>

  <Tab title="CLAIMABLE">
    In `CLAIMABLE` mode, yield accumulates separately from the account's balance and can be claimed to any recipient address any point by the account's [governor](/building/guides/eth-yield#governor). In this case the balance would be:

    ```solidity theme={null}
    balance   = account.fixed
    claimable = account.shares * sharePrice + account.remainder - account.fixed
    ```

    The `claimable` value refers to yield that this account can claim.

    <Warning>There is no `Transfer` event emitted when yield is claimed which can sometimes lead to confusion.</Warning>
  </Tab>
</Tabs>

While modifying the type of the state trie is a significant change, there is no difference from the perspective of a single transaction; Blast's `BALANCE` opcode behaves the same as it normally does, so smart contracts don't need to consider their account's shares.

To remain EVM compatible, Blast's share system guarantees wei-level precision, allowing accounts with rebasing balances to transfer precise amounts of wei to accounts with non-rebasing balances and vice versa.

# Global Share Price

The global share price that determines how much ETH each share is worth is stored in the [SharesBase](https://blastscan.io/address/0x4300000000000000000000000000000000000000#readProxyContract) predeploy at address `0x4300000000000000000000000000000000000000`.

This contract tracks the share price, the total number of shares, and the total amount of ETH that has yet to be reflected in the share price. You can read the current ETH share price by calling  `SharesBase::price()` as demonstrated below using `cast call` or the `eth_call` RPC:

<CodeGroup>
  ```bash cast call Example theme={null}
  cast call 0x4300000000000000000000000000000000000000 "price()(uint256)" \
    --block 2097152 --rpc-url https://rpc.blast.io \
    | awk '{ printf "%.9f gwei/share\n", $1 / 1e9 }'
  ```

  ```bash eth_call RPC Example theme={null}
  curl \
    --data '{"id":0,"jsonrpc":"2.0","method":"eth_call","params":[{"from":null,"to":"0x4300000000000000000000000000000000000000","data":"0xa035b1fe"}, "0x200000"]}' \
    --header "Content-Type: application/json" https://rpc.blast.io \
    --silent | jq '.result' | xargs printf '%0.2f\n' | jq -r '"\(./1e9) gwei/share"'
  ```
</CodeGroup>

<Note>In these examples we pipe the output into `awk` and `jq` for styling purposes to show the units of the return value.</Note>

You can also index the `NewPrice(uint256 price)` event emitted by this contract to get the new global share price whenever an update occurs. Generally, this update happens every day at midnight UTC, but this schedule is not guaranteed in code and may be subject to change.

# Indexing Account Shares

As mentioned above, for the most accurate results it is recommended that you index account shares instead of account balances directly.

For the most part, this works the same way as indexing balances on ETH mainnet: we first identify which accounts were touched in the transactions within a given block and then re-fetch the balances of those accounts on that block.

Usually, these ETH balances are re-fetched using the `eth_getBalance` RPC method, but on Blast we need to be able to read and save the account's `shares` value instead. Blast nodes expose a new RPC method, `eth_getBalanceValues`, to support indexing the `flags`, `shares`, `remainder`, and `fixed` fields for accounts.

### `eth_getBalanceValues`

This RPC method exposes the Blast-specific fields of the `StateAccount` struct.

#### Request

<ParamField body="address" type="string" required={true}>
  Same as `eth_getBalance`
</ParamField>

<ParamField body="blockNumber" type="string" required={true}>
  Same as `eth_getBalance`; hex or `“latest”`, `“pending”`, etc
</ParamField>

<ParamField body="id" type="number" required={true}>
  Unique request identifier
</ParamField>

**Request Example**

```bash theme={null}
curl -s -X POST \
  -H "Content-Type: application/json" \
  --url <rpc-url>
  --data '{
        "jsonrpc":"2.0",
        "method":"eth_getBalanceValues",
        "params":["0x4200000000000000000000000000000000000000","latest"],
        "id":1
    }'   
```

#### Response

<ResponseField name="jsonrpc" type="string">
  String representing RPC version number
</ResponseField>

<ResponseField name="result" type="object">
  Object containing `fixed`, `flags`, `remainder`, and `shares`
</ResponseField>

<Expandable defaultOpen={true}>
  <ResponseField name="fixed" type="string">
    Hex number string, e.g. `"0x1"`
  </ResponseField>

  <ResponseField name="flags" type="string">
    Hex number string representing one of three [yield modes](#yield-modes):<br />

    * `"0x0"`: AUTOMATIC
    * `"0x1"`: VOID
    * `"0x2"`: CLAIMABLE
  </ResponseField>

  <ResponseField name="remainder" type="string">
    Hex number string, e.g. `"0x1"`
  </ResponseField>

  <ResponseField name="shares" type="string">
    Hex number string, e.g. `"0x1"`
  </ResponseField>
</Expandable>

<ResponseField name="id" type="number">
  Unique request identifier
</ResponseField>

**Response Example**

```bash theme={null}
{
  "jsonrpc": "2.0",
  "result":  {
    "fixed": "0x0",
    "flags": "0x1",
    "remainder": "0x0",
    "shares": "0x0"
  },
  "id": 1
}
```

## Edge Cases

On Ethereum mainnet, `selfdestruct` allows ETH to be sent to a beneficiary address without triggering any code at that address. As a result, the beneficiary account's balance changes without there being any `call` made. Indexers must handle this edge case to ensure perfect accounting.

Blast introduces a similar edge case that indexers should be aware of. Accounts set to `CLAIMABLE` yield mode can claim accumulated yield to an arbitrary beneficiary address. This claim operation works the same as `selfdestruct` in that it can increase an arbitrary account's balance without a `call`.

While this edge case is exceptionally rare and not particularly important to handle, we include it here for completeness.
