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

# EIP-8021 calldata table function

> Parse EIP-8021 builder codes from calldata with the `functions.base_l2.call_data_8021` table function.

# EIP-8021 calldata table function

[EIP-8021](https://eips.ethereum.org/EIPS/eip-8021) defines a standard for embedding builder identification codes at the end of transaction calldata.

Dune exposes this as the table function `functions.base_l2.call_data_8021`. It reads calldata from an input table, keeps the input columns, and adds parsed EIP-8021 fields for rows that contain a valid EIP-8021 suffix.

Rows without the EIP-8021 suffix are omitted from the result.

## Syntax

```sql theme={null}
SELECT *
FROM TABLE(functions.base_l2.call_data_8021(
  input => TABLE(<query>),
  calldata => DESCRIPTOR(<calldata_column>)
))
```

## Arguments

* `input`: The input table or subquery that contains a calldata column.
* `calldata`: Optional descriptor pointing to the calldata column in `input`.
  If omitted, the function looks for a column named `calldata`.

The referenced calldata column must be `varchar`.

## Output columns

The table function passes through the original input columns and adds:

| Column | Type | Description |
| - | - | - |
| `original_tx_data` | `varchar` | Original calldata without the EIP-8021 suffix |
| `schema_type` | `varchar` | Parsed schema label: `Schema 0: Canonical Registry`, `Schema 1: Custom Registry`, `Schema 2: CBOR`, or `Unknown Schema` |
| `codes_hex` | `varchar` | Builder codes as hex |
| `custom_registry_address` | `varchar` | Custom registry address for schema 1, otherwise `NULL` |
| `codes_readable` | `varchar` | UTF-8 decoded builder codes |
| `codes_array` | `array(varchar)` | Builder codes split into an array |
| `cbor_data` | `varchar` | JSON representation of schema 2 CBOR payloads |
| `erc_8021_suffix` | `varchar` | The EIP-8021 magic bytes suffix |

## Examples

### Parse transaction calldata from `base.transactions`

```sql theme={null}
SELECT
  tx_hash,
  block_time,
  schema_type,
  codes_readable,
  codes_array
FROM TABLE(functions.base_l2.call_data_8021(
  input => TABLE(
    SELECT
      hash AS tx_hash,
      block_time,
      cast(data as varchar) AS calldata
    FROM base.transactions
    WHERE block_time >= now() - interval '7' day
  )
))
LIMIT 100
```

### Use the default `calldata` column name

```sql theme={null}
SELECT
  tx_hash,
  schema_type,
  codes_readable
FROM TABLE(functions.base_l2.call_data_8021(
  input => TABLE(
    VALUES
      (
        '0xdeadbeef',
        '0x722c6182000000000000000000000000000000000000000000000000000000000000000163625f77616c6c6574090080218021802180218021802180218021'
      )
  ) AS t(tx_hash, calldata)
))
```

### Override the calldata column name

```sql theme={null}
SELECT
  tx_hash,
  schema_type,
  codes_readable
FROM TABLE(functions.base_l2.call_data_8021(
  input => TABLE(
    VALUES
      (
        '0xdeadbeef',
        '0x722c6182000000000000000000000000000000000000000000000000000000000000000163625f77616c6c6574090080218021802180218021802180218021'
      )
  ) AS t(tx_hash, call_data),
  calldata => DESCRIPTOR(call_data)
))
```

### Parse schema 2 CBOR calldata

```sql theme={null}
SELECT
  schema_type,
  codes_readable,
  codes_array,
  cbor_data
FROM TABLE(functions.base_l2.call_data_8021(
  input => TABLE(
    VALUES
      (
        '0xabcda26161656d796170706177686d7977616c6c657400140280218021802180218021802180218021'
      )
  ) AS t(calldata)
))
```

### Filter for a specific builder code

```sql theme={null}
SELECT
  tx_hash,
  block_time,
  codes_readable
FROM TABLE(functions.base_l2.call_data_8021(
  input => TABLE(
    SELECT
      hash AS tx_hash,
      block_time,
      cast(data as varchar) AS calldata
    FROM base.transactions
    WHERE block_time >= now() - interval '7' day
  )
))
WHERE contains(codes_array, 'cb_wallet')
LIMIT 100
```

## Supported schema types

* **Schema 0: Canonical Registry**: Builder codes plus the EIP-8021 suffix
* **Schema 1: Custom Registry**: Builder codes plus a custom registry address
* **Schema 2: CBOR**: CBOR-encoded builder metadata exposed through both `codes_*` fields and `cbor_data`

## EIP-8021 suffix structure

Schema 0 and schema 1 are parsed from the end of calldata in this order:

| Component | Size | Description |
| - | - | - |
| Builder codes | Variable | UTF-8 encoded builder identification codes |
| Registry address | 20 bytes | Only present for schema 1 |
| Codes length | 1 byte | Length of the builder code payload |
| Schema ID | 1 byte | `0x00` or `0x01` |
| Magic bytes | 16 bytes | `0x80218021802180218021802180218021` |

Schema 2 uses:

| Component | Size | Description |
| - | - | - |
| CBOR payload | Variable | CBOR map containing builder metadata |
| CBOR length | 2 bytes | Length of the CBOR payload |
| Schema ID | 1 byte | `0x02` |
| Magic bytes | 16 bytes | `0x80218021802180218021802180218021` |

## Use Cases

* **Builder attribution**: Track which wallet or tool produced a transaction
* **Wallet analytics**: Measure adoption of builder codes across applications
* **ERC-4337 analysis**: Parse builder metadata from UserOperation calldata
* **Schema research**: Compare canonical registry, custom registry, and CBOR-based usage

## Notes

* The function currently expects calldata as `varchar`, not `varbinary`
* If your source column is `varbinary` (for example `base.transactions.data`), cast it to `varchar` before passing it into the table function
* Input rows without the EIP-8021 magic bytes are filtered out of the result
* Builder codes are typically comma-separated identifiers such as `cb_wallet`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.