Skip to main content

Protocol Reference

Quick reference guide for protocol versions, constants, standards, and specifications.

Quick Navigation

Jump to a section:


Protocol Versions

Nitrolite Protocol

PropertyValue
Version0.5.0
StatusMainnet deployments live; not production yet
CompatibilityEVM-compatible chains

Supported Chains: Ethereum, Polygon, Arbitrum One, Optimism, Base, and other EVM-compatible networks.

Nitro RPC Protocol

VersionStatusFeatures
0.2LegacyBasic state updates only
0.4CurrentIntent system (OPERATE, DEPOSIT, WITHDRAW)
Version Recommendation

Always use NitroRPC/0.4 for new implementations. Version 0.4 adds the intent system for app sessions, enabling dynamic fund management (deposits and withdrawals) within active sessions.

Breaking Changes:

  • NitroRPC/0.4 introduces the intent parameter in submit_app_state
  • NitroRPC/0.2 sessions cannot use DEPOSIT or WITHDRAW intents
  • Protocol version is set during app session creation and cannot be changed

State Intent System

Channel states are classified by state.intent (uint8) to signal their purpose. The Solidity enum defines:

StateIntent Enumeration

enum StateIntent {
OPERATE, // 0: Normal updates (challenge/checkpoint)
INITIALIZE, // 1: Channel funding/creation
RESIZE, // 2: In-place capacity change
FINALIZE // 3: Cooperative closure
}

Intent Usage

IntentValueWhen UsedMethod
INITIALIZE1Channel creationCustody.create()
RESIZE2Channel resizeCustody.resize()
FINALIZE3Cooperative closureCustody.close()
OPERATE0Challenge/checkpointCustody.challenge(), Custody.checkpoint()

Example:

// Creation state
state.intent = 1 // INITIALIZE
state.version = 0
state.data = "0x" // Empty for basic channels

// Closing state
state.intent = 3 // FINALIZE
state.version = currentVersion + 1
state.data = "0x"
Intent Validation

Smart contracts validate the intent field to ensure proper channel lifecycle. Incorrect intent values will cause transactions to revert.


Participant Indices

In a standard payment channel, participants are identified by their array index.

Index 0: Creator (User)

Role: Creator

Responsibilities:

  • Initiates channel creation
  • Typically the one depositing funds
  • First to sign states (state.sigs[0])
  • Calls Custody.create() on-chain

Example:

channel.participants[0] = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" // User

Index 1: Clearnode

Role: Service provider

Responsibilities:

  • Co-signs the initial state before on-chain create(); there is no separate join() call
  • Provides off-chain services (Nitro RPC, unified balance management)
  • Second to sign states (state.sigs[1])

Example:

channel.participants[1] = "0x123456789abcdef0123456789abcdef012345678" // Clearnode
Signature Order Critical

Signatures array order MUST match participants array order. Mismatched signatures will cause transaction failures.

state.sigs[0] = creator_signature   // Must be from participants[0]
state.sigs[1] = clearnode_signature // Must be from participants[1]

Channel Status State Machine

Channel lifecycle is governed by status transitions.

Status Enumeration

enum Status {
VOID, // 0: Channel does not exist
INITIAL, // 1: Creation in progress, awaiting all participants
ACTIVE, // 2: Fully funded and operational
DISPUTE, // 3: Challenge period active
FINAL // 4: Ready to be closed and deleted
}

State Transition Diagram

Valid Transitions

FromToTriggerNotes
VOIDINITIALcreate() (creator only)Legacy flow; awaiting other participants
VOIDACTIVEcreate() (all sigs present)Current flow; both participants co-sign initial state
INITIALACTIVEjoin()Remaining participants join
ACTIVEDISPUTEchallenge()Dispute initiated
ACTIVEFINALclose()Cooperative closure
DISPUTEACTIVEcheckpoint()Newer state accepted
DISPUTEFINALclose()Challenge timeout
Quick Closure

The fastest way to close a channel is ACTIVE → FINAL via cooperative close(). This skips the challenge period entirely.


Signature Standards

On-Chain Signatures (Solidity)

Used in smart contract transactions (create, join, close, challenge, resize).

Format: Variable-length byte arrays supporting multiple signature types (since v0.3.0)

Structure:

struct State {
// ... other fields ...
bytes[] sigs; // Array of signatures from participants
}

Supported Types:

  • ECDSA (65 bytes): Standard signatures from EOA wallets
  • ERC-1271: Smart contract wallet signatures
  • ERC-6492: Counterfactual contract signatures (not yet deployed)

Hash: Raw packedState (no EIP-191 prefix for chain-agnostic compatibility)

Example:

packedState = keccak256(abi.encode(channelId, state.intent, state.version, state.data, state.allocations))
signature = sign(packedState, participantPrivateKey) // Raw hash, no prefix

Off-Chain Signatures (Nitro RPC)

Used in RPC requests and responses over RPC.

Format: 0x-prefixed hex string (typically ECDSA from session keys)

Typical Length: 65 bytes for ECDSA

  • r: 32 bytes
  • s: 32 bytes
  • v: 1 byte

Representation: 130 hex characters + 0x prefix

Example:

signature = "0x1234567890abcdef...xyz" // 132 characters total (ECDSA)

Computed Over:

rpcHash = keccak256(JSON.stringify(req))
signature = sign(rpcHash, sessionPrivateKey)
Session Key Signatures

Off-chain RPC signatures are typically ECDSA from session keys (EOA wallets), but the protocol supports other signature types for future flexibility.

Chain-Agnostic Signatures

On-chain signatures do NOT use EIP-191 or EIP-712 prefixes to maintain chain-agnostic compatibility. This differs from typical Ethereum signing patterns. Off-chain RPC signatures (e.g., authentication) DO use EIP-712 for better wallet UX.


EIP References

Ethereum Improvement Proposals referenced or used by the protocol.

EIP-191: Signed Data Standard

Status: Not used in on-chain signatures (chain-agnostic design)
Link: https://eips.ethereum.org/EIPS/eip-191

Why not used for on-chain: On-chain signatures are computed over raw packedState hash without EIP-191 prefix to maintain compatibility across different EVM chains and potential non-EVM implementations.

EIP-712: Typed Structured Data Hashing

Status: Used for off-chain RPC authentication
Link: https://eips.ethereum.org/EIPS/eip-712

Usage: Authentication flow uses EIP-712 typed data for signing the Policy structure (challenge, wallet, session_key, expires_at, scope, allowances) with the main wallet. This provides better wallet UX by displaying human-readable signing data.

EIP-1271: Contract Signature Validation

Status: Supported by adjudicators
Link: https://eips.ethereum.org/EIPS/eip-1271

Usage: Enables smart contract wallets to sign state updates as participants.

EIP-20 (ERC-20): Token Standard

Status: Required for all assets
Link: https://eips.ethereum.org/EIPS/eip-20

Usage: All assets must be ERC-20 compliant tokens. The Custody Contract uses transferFrom and transfer methods.

Standards Compliance

While the protocol references these EIPs, implementation details may vary. Always consult the specific smart contract code for authoritative behavior.


Protocol Constants

The only protocol-wide constants defined in code are:

uint256 constant PART_NUM   = 2; // Channels are always 2-party
uint256 constant CLIENT_IDX = 0; // Client/creator participant index
uint256 constant SERVER_IDX = 1; // Server/clearnode participant index

All channel arrays (participants, allocations, sigs) and state validation logic rely on these indices and fixed participant count.


Next Steps

Now that you have the complete protocol reference:

  1. Terminology: Review Terminology for all term definitions
  2. Communication Flows: See Communication Flows for sequence diagrams
  3. Implementation Guide: Follow Implementation Checklist to build compliant clients
  4. Channel Lifecycle: See Channel Lifecycle for detailed state transitions
Reference Updates

This reference reflects protocol version 0.5.0. For the latest updates, check the Nitrolite repository or use get_config to query clearnode capabilities dynamically.