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
| What | Address |
|---|---|
| Program ID | 9ATDq9dpDcM517hncjHnbWsBXzsNxKvqdfJ4L5qHJYy2 |
| ProgramData (upgradeable loader) | BNQ6uyEmDmEUTG2wrxePFKC9w6z7GQZVFzPP5Zo1A3k9 |
| NLS token (mirror mint) | B9Vhg6XrNswZvLdKgpKhZ9Fj9yV7j2RxQKUaq5fmuphv |
| Statics address lookup table | 75nJQPCfAwcrxHJG2kbcbozNEBKJtUZF8L22KNXxnRtJ |
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].
| Entity | Seed 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 stores | channel 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
| Account | Address | What it does |
|---|---|---|
| Program state | 6SJgbqjAFxvv3KnVjEjD54H8JEG74Y7ANksrXh1cj1Q7 | Records the instance configuration and the next client / connection / channel ordinals. |
| Vault authority | 6xDAvqaePki3Re9NN8YHLhrN2e1cZ4a2nzL2VXeDawWp | The 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 pointer | 78Wx6LowbsBdvECQGYBuoFrfZD3boQhbi36kS2ia9Svf | Holds 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 table | 75nJQPCfAwcrxHJG2kbcbozNEBKJtUZF8L22KNXxnRtJ | A 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:
| Entity | Address |
|---|---|
07-tendermint-0 (client) | H66HFVTja92BRvYHPaFAB99JGzTLuhRoPSXU7SxdjdRG |
| Client's connection list | 3Nhy9pmkdKcYK6Xi5La5nCE779V76HnW41aY5iF9Dnp6 |
connection-0 | 2GDasyhvUAbHmSC18Xxcdpkxnz71GEYBzVnMUfcNvpvq |
| Connection's channel list | AVRfVWARk7K6xMbTHhmbn43BeG7Vzj6A16hXUViuudvv |
channel-0 - ICS-20 transfer
The token-transfer channel: port transfer, version ics20-1, connected to
Nolus channel-61957.
| Account | Address | What it does |
|---|---|---|
| Channel end | 9PVMGoqDKSZYCPyCoA6ZWusbme78eZkQ1tTxXLqMQCuF | Channel state and counterparty identity |
| Next send sequence | B1sHvbsuSUBzN3Anma2vdhgddkNY9yWyRmqAS9nCtjvN | Ordinal for the next outgoing packet |
| Packet commitments | Aomi2CxYwtbkR71B9yJPyVZBh1GoQEGupfTEKpeipBb4 | Commitments of sent, not-yet-acknowledged packets |
| Packet receipts | ugqGrE1HqQBfo1dmXwfAq546qK3k3bDdVuSxtULj9Lh | Receipts of received packets (replay protection) |
| Packet acknowledgements | 2tprvXyrbe4EMgJMs4dMKN9U5ggKbXWAVirtmv6qvPB9 | Acknowledgements written for received packets |
| Token census | 91gUYsWAiCbnMJLzacBaXaFLhFcTMuaUZuHpMXQxhw8b | Counts 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.
| Account | Address | What it does |
|---|---|---|
| Channel end | 8swVa22QfN6rX5Tb5DmTV234KMyR9esKgHKkKkba9s21 | Channel state and counterparty identity |
| Lease channel binding | GGyDtSVRtJ7harZmwd2z4Y12e4ULVZYiE2Cp8sLJmR7N | Binds the lease channel to its transfer channel (channel-0) and records the swap engine the channel is served by (jupiter) |
| Next send sequence | DvLjrrvAYSXh8tEhhNpbPhYLAamnZUkDJ4cWwnJ1nr1k | Ordinal for the next outgoing packet |
| Packet commitments | CFsMZSMTadBjUdF3yj8GB6caDEgqaKT85sFuneyJvuEE | Commitments of sent, not-yet-acknowledged packets |
| Packet receipts | 8o28mjzqXce4GJXyLtYHUjJBZf1QRYKtDwhEut4V7V1T | Receipts of received packets (replay protection) |
| Packet acknowledgements | 7hzirijfq5JJCYvYGh7mq4tRGy4xxnpsjR3hL3jsEE7W | Acknowledgements written for received packets |
| Token census | F3Eb5eAFtvd7HdNMVsrRum8Fug9S2WXQJLjkW2LoSRiZ | Counts 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:
| What | Value |
|---|---|
| Mint | B9Vhg6XrNswZvLdKgpKhZ9Fj9yV7j2RxQKUaq5fmuphv |
| Decimals | 6 (same as unls on Nolus) |
| Mint authority | 6xDAvqaePki3Re9NN8YHLhrN2e1cZ4a2nzL2VXeDawWp (the vault authority) |
| Derivation | channel-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:
| Token | Mint | Escrow |
|---|---|---|
| USDC | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v | A57C37YLZz412hQs6vPNYBUucRGkX5fe9bbKnwQDeRhs |
| Wrapped SOL | So11111111111111111111111111111111111111112 | 9GUpG4SwCjEjZfHxkXbB5HchmWhvNLnij5VNbrGv8S7u |
| cbBTC | cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij | DXvMe3wow8H5y2w4gPgEQBX19CpMQp7h3tK7u6nWKvzE |
| ETH (Wormhole) | 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs | DpCN5TnWgSmdV5YQh97ThKa4fC1vA5ZVK697JYgEEQXP |
| HYPE | 98sMhvDwXj1RQi5c5Mndm3vPe9cBqPrbLaufMXFNMh5g | EkBvfVYmpfYMPThZygDu61QH2VVNqJKeKm2QiMaLXyib |
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.