Nolus Docs
IBC

Solray

The Nolus IBC program on Solana - production addresses and what each on-chain account does.

Solray is the IBC implementation Nolus runs natively on Solana - a single on-chain program that hosts the IBC core state (client, connection, channels) and two IBC applications on top of it:

  • ICS-20 token transfer - moves tokens between Nolus and Solana in both directions: Solana-native tokens are locked in per-token escrow accounts, and tokens arriving from Nolus (such as NLS) are minted as "mirror" SPL tokens.
  • Remote Lease - executes lease operations that a Nolus lease contract requests on Solana: opening a position, swapping via a DEX aggregator (currently Jupiter), transferring out, and closing. A lease is a margin position - the same Lease described under Protocol > Spot Margin; "Remote" because the position's assets live on Solana while the contract governing it runs on Nolus.

As on every IBC connection, off-chain relayer processes carry the packets: they pick up what one chain emits, submit it to the other, and return the acknowledgement.

This page is a reference for the production deployment on Solana mainnet: the accounts the program controls, what each does, and its concrete address.

Production deployment

WhatAddress
Program ID9ATDq9dpDcM517hncjHnbWsBXzsNxKvqdfJ4L5qHJYy2
ProgramData (upgradeable loader)BNQ6uyEmDmEUTG2wrxePFKC9w6z7GQZVFzPP5Zo1A3k9
NLS token (mirror mint)B9Vhg6XrNswZvLdKgpKhZ9Fj9yV7j2RxQKUaq5fmuphv
Statics address lookup table75nJQPCfAwcrxHJG2kbcbozNEBKJtUZF8L22KNXxnRtJ

The program is deployed through Solana's upgradeable BPF loader; upgrades are controlled by the upgrade authority recorded in the ProgramData account.

How addresses are derived

Every account the program owns is a Program Derived Address (PDA) under the program ID. Seeds are short, fixed two-byte designators chained from parent to child, with 2-byte big-endian ordinals for numbered entities. The production instance uses instance ordinal 0, so every path starts with ["pr", 0u16].

EntitySeed path
Program (instance)["pr", ordinal]
Vault authority["pr", 0, "va"]
Statics table pointer["pr", 0, "st"]
Client N["pr", 0, "cl", N]
Client N's connection list["pr", 0, "cl", N, "cc"]
Connection N["pr", 0, "cn", N]
Connection N's channel list["pr", 0, "cn", N, "co"]
Channel N["pr", 0, "ch", N]
Per-channel storeschannel seeds + "ns" / "pq" / "rc" / "pa" / "tc" / "le"
Escrow (per token)channel seeds + ["es", mint pubkey]
Mirror mint (per token)channel seeds + ["mt", sha256(symbol)]
Lease (per position)channel seeds + ["ls", lease address]
In-flight transfer counter (per sender)["pr", 0, "in", sender pubkey]

Anyone can re-derive and verify every address below with the standard find_program_address over these seeds, or query them with the solray CLI's derive and query commands.

Program-wide accounts

AccountAddressWhat it does
Program state6SJgbqjAFxvv3KnVjEjD54H8JEG74Y7ANksrXh1cj1Q7Records the instance configuration and the next client / connection / channel ordinals.
Vault authority6xDAvqaePki3Re9NN8YHLhrN2e1cZ4a2nzL2VXeDawWpThe program's signing identity - a PDA with no private key that only the program can sign for. It is the mint authority of every mirror mint (including NLS), the owner of every escrow account, the authority of the address lookup tables, and the SOL source that funds rent for accounts the program creates.
Statics table pointer78Wx6LowbsBdvECQGYBuoFrfZD3boQhbi36kS2ia9SvfHolds the address of the deployment-wide statics lookup table (a lookup table's address depends on the slot it was created in, so it cannot be derived - this PDA is where it is discovered).
Statics lookup table75nJQPCfAwcrxHJG2kbcbozNEBKJtUZF8L22KNXxnRtJA Solana address lookup table holding the accounts every transaction needs (program state, channels, packet stores, token programs) plus each registered token's mint and escrow. Lets packet-delivery transactions fit Solana's transaction size limit. Owned by the lookup-table program; its authority is the vault authority.

IBC entities

One IBC client, one connection, and two channels are live:

EntityAddress
07-tendermint-0 (client)H66HFVTja92BRvYHPaFAB99JGzTLuhRoPSXU7SxdjdRG
Client's connection list3Nhy9pmkdKcYK6Xi5La5nCE779V76HnW41aY5iF9Dnp6
connection-02GDasyhvUAbHmSC18Xxcdpkxnz71GEYBzVnMUfcNvpvq
Connection's channel listAVRfVWARk7K6xMbTHhmbn43BeG7Vzj6A16hXUViuudvv

channel-0 - ICS-20 transfer

The token-transfer channel: port transfer, version ics20-1, connected to Nolus channel-61957.

AccountAddressWhat it does
Channel end9PVMGoqDKSZYCPyCoA6ZWusbme78eZkQ1tTxXLqMQCuFChannel state and counterparty identity
Next send sequenceB1sHvbsuSUBzN3Anma2vdhgddkNY9yWyRmqAS9nCtjvNOrdinal for the next outgoing packet
Packet commitmentsAomi2CxYwtbkR71B9yJPyVZBh1GoQEGupfTEKpeipBb4Commitments of sent, not-yet-acknowledged packets
Packet receiptsugqGrE1HqQBfo1dmXwfAq546qK3k3bDdVuSxtULj9LhReceipts of received packets (replay protection)
Packet acknowledgements2tprvXyrbe4EMgJMs4dMKN9U5ggKbXWAVirtmv6qvPB9Acknowledgements written for received packets
Token census91gUYsWAiCbnMJLzacBaXaFLhFcTMuaUZuHpMXQxhw8bCounts the channel's live escrows, mirror mints, and bound lease channels - the teardown gates that keep the channel from closing while tokens are still keyed under it

channel-1 - Remote Lease

The lease channel: version nls-remote-lease.v1+transfer=channel-0, connected to Nolus channel-61961 on the Nolus protocol's contract port (wasm.nolus1xd9sgdu3lvwm0pzrxg3c3lxwvuwkc6jgzk43zkgzjnndrdp5shvsfv3uzp). The version string names the transfer channel it is paired with: lease operations move funds over channel-0.

AccountAddressWhat it does
Channel end8swVa22QfN6rX5Tb5DmTV234KMyR9esKgHKkKkba9s21Channel state and counterparty identity
Lease channel bindingGGyDtSVRtJ7harZmwd2z4Y12e4ULVZYiE2Cp8sLJmR7NBinds the lease channel to its transfer channel (channel-0) and records the swap engine the channel is served by (jupiter)
Next send sequenceDvLjrrvAYSXh8tEhhNpbPhYLAamnZUkDJ4cWwnJ1nr1kOrdinal for the next outgoing packet
Packet commitmentsCFsMZSMTadBjUdF3yj8GB6caDEgqaKT85sFuneyJvuEECommitments of sent, not-yet-acknowledged packets
Packet receipts8o28mjzqXce4GJXyLtYHUjJBZf1QRYKtDwhEut4V7V1TReceipts of received packets (replay protection)
Packet acknowledgements7hzirijfq5JJCYvYGh7mq4tRGy4xxnpsjR3hL3jsEE7WAcknowledgements written for received packets
Token censusF3Eb5eAFtvd7HdNMVsrRum8Fug9S2WXQJLjkW2LoSRiZCounts the channel's live leases - the channel cannot be finalized while any lease is still open

Each open lease (margin position) additionally owns a small set of dynamic accounts keyed by the Nolus lease contract address: the Lease PDA itself, a per-lease authority PDA whose associated token accounts hold the position's funds, and a per-lease address lookup table. These are created when a lease opens and closed (rent reclaimed) when it closes.

While a sender has ICS-20 transfers awaiting settlement, the program additionally keeps a per-sender in-flight transfer counter PDA (seed designator in), keyed by the packet sender's address - the lease authority for lease-flow sends, the funding wallet for wallet sends. It is created at the sender's first in-flight send and closed once the count returns to zero; a lease cannot be closed while its authority's counter still exists.

Tokens

NLS on Solana

NLS arriving from Nolus over channel-0 is minted as a mirror SPL token:

WhatValue
MintB9Vhg6XrNswZvLdKgpKhZ9Fj9yV7j2RxQKUaq5fmuphv
Decimals6 (same as unls on Nolus)
Mint authority6xDAvqaePki3Re9NN8YHLhrN2e1cZ4a2nzL2VXeDawWp (the vault authority)
Derivationchannel-0 seeds + ["mt", sha256("unls")]

The supply on Solana is exactly the amount transferred over IBC and not yet returned: the program mints on each inbound transfer and burns on each outbound one. No wallet holds minting rights - only the program, via the vault authority PDA.

Registered Solana-native tokens

Solana-native tokens transfer to Nolus by being locked in a per-token escrow account - an SPL token account owned by the vault authority. Registered on channel-0:

TokenMintEscrow
USDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vA57C37YLZz412hQs6vPNYBUucRGkX5fe9bbKnwQDeRhs
Wrapped SOLSo111111111111111111111111111111111111111129GUpG4SwCjEjZfHxkXbB5HchmWhvNLnij5VNbrGv8S7u
cbBTCcbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMijDXvMe3wow8H5y2w4gPgEQBX19CpMQp7h3tK7u6nWKvzE
ETH (Wormhole)7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxsDpCN5TnWgSmdV5YQh97ThKa4fC1vA5ZVK697JYgEEQXP
HYPE98sMhvDwXj1RQi5c5Mndm3vPe9cBqPrbLaufMXFNMh5gEkBvfVYmpfYMPThZygDu61QH2VVNqJKeKm2QiMaLXyib

Program IDL

A machine-readable IDL for the program is published at /idl/solray.json in the Anchor 0.30 JSON format. It describes all 36 instructions - discriminators, argument layouts, ordered account lists with signer/writable flags - plus the decodable account-state layouts, the PDA seed constants, and the program's error codes, so explorers and indexers can decode Solray transactions and accounts. The file's own top-level docs array carries the decoding rules an integrator needs (wire framing, the engine account tails, the lease packet envelope, error-log parsing).

Every address on this page is either directly readable on-chain or re-derivable from the seed table above with the standard find_program_address - the seed constants in the IDL carry the exact designator bytes.

On this page