> For the complete documentation index, see [llms.txt](https://igra-labs.gitbook.io/igralabs-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://igra-labs.gitbook.io/igralabs-docs/for-developers/architecture/specifications/igra-transaction-protocol.md).

# Igra Transaction Protocol

This document defines the requirements and interpretation rules for [L1-submitted Transactions](#id-1.1-l1-submitted-transactions) of the Igra protocol — transactions posted to the Kaspa base layer (L1) and consumed by the Igra execution layer.

> Igra protocol may also define additional system-level transaction classes in the future, created directly on Igra without being posted to L1. These are mentioned here only for context and are **out of scope** for this document.

***

## Document Version History

| Version | Date       | Author    | Description                                                                                          |
| ------- | ---------- | --------- | ---------------------------------------------------------------------------------------------------- |
| v0.0    | 2025-03-23 | Igra Team | Initial draft with support for 1-to-1 Payload transactions (zipped and unzipped).                    |
| v0.1    | 2025-06-27 | Igra Team | Refactored following the introduction of Tx ID mining.                                               |
| v0.2    | 2025-11-26 | Igra Team | Removed Start and Synthetic Transactions; updated supported types, payload semantics, and numbering. |

***

## 1. Transaction Classes in Igra

Igra currently defines a single class of transactions: [L1-submitted Transactions](#id-1.1-l1-submitted-transactions).

### 1.1 L1-submitted Transactions

These are regular transactions posted on the Kaspa base layer (L1) with a recognizable `Payload`. They are:

* Validated at both the L1 and Igra layers
* Used to carry executable Igra data or instructions
* The main subject of this document

#### Validation Rules

L1-submitted Igra transactions are subject to **two layers of validation**:

**L1-level Rules**

These rules are based on the L1 chain state and require knowledge of L1 logic. As such, they **cannot** be validated by the Igra execution layer.

A key requirement, applicable to **all** [L1-submitted Transactions](#id-1.1-l1-submitted-transactions), is that the L1 transaction ID must match a predefined pattern (see Igra Design Note: L1 Payload Format and Filtering by txID).

Other L1-level validation rules include:

* A transaction must include the L1 `Payload` field starting with [`version`](#id-3.1-payload-format)
* A transaction may need to create or spend specific UTXOs (see [Entry transaction](#id-4.3-entry) for an example)
* Or, it must use specific locking and unlocking scripts

> Example: The [Entry Transaction](#id-4.3-entry) must create the [KAS Locking UTXO](#kas-locking-utxo).

**Igra-level Rules**

These rules require knowledge of Igra logic and access to the Igra state.

Examples:

* The [Igra content](#id-3.1-payload-format) in the L1 payload must be an RLP encoded and correctly signed EVM transaction
* Metadata (in [metadata-based transactions](#metadata-based-transactions)) must match the current Igra state

***

## 2. L1-submitted Transaction Types

The following L1-submitted transaction types and their corresponding identifiers are defined:

| TxTypeId (4 bits) | Type Name                  | Category            | Status    |
| ----------------- | -------------------------- | ------------------- | --------- |
| b0001             | Igra Param Update          | Metadata            | Reserved  |
| b0010             | Entry                      | Metadata            | Supported |
| b0011             | Exit                       | Metadata            | Planned   |
| b0100             | 1-to-1 Unzipped Payload    | Raw Igra Tx         | Supported |
| b0101             | 1-to-1 Zipped Payload      | Raw Igra Tx         | Reserved  |
| b0110             | 1-to-many Unzipped Payload | Raw Igra Tx (batch) | Reserved  |
| b0111             | 1-to-many Zipped Payload   | Raw Igra Tx (batch) | Reserved  |
| b1000 .. b1111    | Reserved                   | —                   | Reserved  |

## 3. L1 Payload

All L1-submitted Igra transactions must embed Igra-specific data in the `Payload` field of the L1 transaction.

### 3.1 Payload Format

All [L1-submitted Transactions](#id-2.-l1-submitted-transaction-types) must include an L1 payload structured as follows:

```
[Version (4 bits)] [txTypeId (4 bits)] [L2Data (≤24,800 bytes)] [Nonce (4 bytes)]
```

* `Version`: 4-bit identifier, set to `0x9`
* `txTypeId`: 4-bit field identifying the type of Igra data (see [Transaction Types](#id-2.-l1-submitted-transaction-types))
* `L2Data`: Igra-specific data, determined by `txTypeId`
* `Nonce`: 4-byte nonce used for tx ID mining

See the Igra Design Note: L1 Payload Format and Filtering by txID for more details.

### 3.2 Payload Semantics

[L1-submitted Transaction types](#id-2.-l1-submitted-transaction-types) fall into two semantic categories:

#### Raw Igra Transactions

Types: `b0100`, `b0101`, `b0110`, `b0111`

* Contain RLP-encoded Igra transaction(s), either compressed or uncompressed
* After processing (decompression and merging), the `L2Data` is sent *as-is* to the EL Client

#### Metadata-based Transactions

Types: `b0001` (not yet supported), `b0010`, `b0011`

* Do **not** include ready-to-execute Igra transactions
* Contain metadata used to **deterministically construct** Igra transactions

***

## 4. Supported Transaction Types

### 4.1 1-to-1 Unzipped Payload

**TxTypeId:** b0100

**Purpose:** Carries a single, uncompressed RLP-encoded Igra transaction.

**L1 Payload:**

```
[0x94] [L2Data: RLP-encoded EVM transaction] [4-byte Nonce]
```

**Requirements:**

* L1 Tx ID must match a predefined pattern
* `L2Data` MUST contain a single RLP-encoded EVM transaction
* `L2Data` MUST not exceed 24,800 bytes
* No restrictions on UTXO inputs/outputs or scripts

**Interpretation:**

`L2Data` is parsed directly as RLP and then sent to the EL client via `eth_sendRawTransaction`

### 4.2 1-to-1 Zipped Payload (Reserved)

**TxTypeId:** b0101

**Status:** Reserved — not implemented yet.

**Purpose:** Same as [1-to-1 Unzipped Payload](#id-4.1-1-to-1-unzipped-payload), but uses ZLIB compression.

**L1 Payload:**

```
[0x95] [L2Data: ZLIB-compressed RLP-encoded EVM transaction] [4-byte Nonce]
```

**Requirements:**

* L1 Tx ID must match a predefined pattern
* `L2Data` MUST be a ZLIB-compressed RLP-encoded EVM transaction
* Decompressed `L2Data` MUST not exceed 24,800 bytes
* No restrictions on UTXO inputs/outputs or scripts

**Interpretation:**

* Decompress with ZLIB
* Parse as RLP
* Submit to EL client via `eth_sendRawTransaction`

### 4.3 Entry

**TxTypeId:** b0010

**Purpose:** Bridges KAS to Igra by locking KAS and issuing an equivalent amount of iKAS.

See Igra Design Doc — Entry Transaction for more details.

**L1 Payload:**

```
[0x92] [L2Data (28 bytes): 20-byte recipient address, 8-byte amount] [4-byte Nonce]
```

**Requirements:**

* L1 Tx ID must match a predefined pattern
* The L1 transaction MUST create the [KAS Locking UTXO](#kas-locking-utxo)
* No restrictions on other inputs or outputs

**Interpretation:**

* `address`: highest 20 bytes of `L2Data` — Igra address to mint iKAS to
* `amount`: lowest 8 bytes of `L2Data` - (unsigned int), in 10^-8 KAS ("dwork" or "SOMPI")

The equivalent iKAS amount will be scaled to 10^-18 units and minted to the Igra address as an EVM "withdrawal" per [EIP-4895](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4895.md).

#### KAS Locking UTXO

* MUST be the first output created by the L1 transaction
* MUST match the amount in the payload (minimum: 1 KAS)
* MUST use the [Entry Locking Script](#entry-locking-script)

**Entry Locking Script**

A P2SH script:

```
[OpBlake2b] [OpData32] [script_hash] [OpEqual]
```

Where `script_hash` is the hash of a redeem script with the following conditions:

* Requires 2-of-3 signatures

**Subnetwork Lane & Version (Toccata / KIP-21)**

Post-Toccata, Igra derives Entries only from the Igra dedicated lane. An Entry transaction MUST use:

| Field               | Value                                                                                         |
| ------------------- | --------------------------------------------------------------------------------------------- |
| subnetwork\_id      | `97b1000000000000000000000000000000000000` (namespace `97b10000` + 16 zero bytes, per KIP-21) |
| Transaction version | `1` (Toccata)                                                                                 |

The Entry payload and locking rules above are unchanged — only the carrier transaction's subnetwork and version differ from the pre-Toccata native (v0) form.

Tooling: kaswallet v3 — pass `--subnetwork-id 97b10000`; it zero-pads the namespace and selects version 1 automatically.

***

## 5. Planned Transaction Types

The following types are defined but not yet supported:

* **Igra Param Update** — signals protocol-level updates
* **Exit** — burns iKAS on Igra, unlocks KAS on L1
* **1-to-many** — atomic batch of Igra transactions
* **Many-to-1** — fragmented Igra txs over several L1 txs (useful for blob data)
* **L1 Tx Notification** — signals specific L1 transaction presence (and parameters) to Igra logic
