Protocol Reference
Quick reference guide for protocol versions, constants, standards, and specifications.
Jump to a section:
- Protocol Versions - Nitrolite & Nitro RPC versions
- State Intent System - Channel state classification
- Participant Indices - Creator & Clearnode positions
- Channel Status - Status transitions
- Signature Standards - On-chain & off-chain formats
- EIP References - Ethereum standards used
- Protocol Constants - Core constants
Protocol Versions
Nitrolite Protocol
| Property | Value |
|---|---|
| Version | 0.5.0 |
| Status | Mainnet deployments live; not production yet |
| Compatibility | EVM-compatible chains |
Supported Chains: Ethereum, Polygon, Arbitrum One, Optimism, Base, and other EVM-compatible networks.
Nitro RPC Protocol
| Version | Status | Features |
|---|---|---|
| 0.2 | Legacy | Basic state updates only |
| 0.4 | Current | Intent system (OPERATE, DEPOSIT, WITHDRAW) |
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
intentparameter insubmit_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
| Intent | Value | When Used | Method |
|---|---|---|---|
INITIALIZE | 1 | Channel creation | Custody.create() |
RESIZE | 2 | Channel resize | Custody.resize() |
FINALIZE | 3 | Cooperative closure | Custody.close() |
OPERATE | 0 | Challenge/checkpoint | Custody.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"
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 separatejoin()call - Provides off-chain services (Nitro RPC, unified balance management)
- Second to sign states (
state.sigs[1])
Example:
channel.participants[1] = "0x123456789abcdef0123456789abcdef012345678" // Clearnode
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
| From | To | Trigger | Notes |
|---|---|---|---|
VOID | INITIAL | create() (creator only) | Legacy flow; awaiting other participants |
VOID | ACTIVE | create() (all sigs present) | Current flow; both participants co-sign initial state |
INITIAL | ACTIVE | join() | Remaining participants join |
ACTIVE | DISPUTE | challenge() | Dispute initiated |
ACTIVE | FINAL | close() | Cooperative closure |
DISPUTE | ACTIVE | checkpoint() | Newer state accepted |
DISPUTE | FINAL | close() | Challenge timeout |
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 bytess: 32 bytesv: 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)
Off-chain RPC signatures are typically ECDSA from session keys (EOA wallets), but the protocol supports other signature types for future flexibility.
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.
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:
- Terminology: Review Terminology for all term definitions
- Communication Flows: See Communication Flows for sequence diagrams
- Implementation Guide: Follow Implementation Checklist to build compliant clients
- Channel Lifecycle: See Channel Lifecycle for detailed state transitions
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.