SETTLEMENT & CONTRACTS / SIDELOT DOCS

Solana escrow reference

PDA seeds, account layouts, instruction encoding, validation, and integer accounting.

Platform reference · Updated October 14, 2026

Solana reference

This chapter covers Solana. For the main Robinhood Chain network, see the Robinhood guide. Wallets, token addresses and settlement mechanics are specific to each network.

Scope of this reference

This chapter documents the implemented escrow v1 source, currently not activated on mainnet. It is for technical review and integration planning. Use the complete ABI for exact account ordering, signer/writable flags, and unused-account placeholders; do not construct a transaction from a guessed address or abbreviated table.

Supported assets are initialized original SPL Token mints against native SOL or canonical mainnet USDC. Token-2022 extensions, transfer hooks, transfer fees and confidential transfers are not supported. SOL quote amounts use native lamports, not a wrapped-SOL quote token account.

PDA derivation and custody authority

Each derivation includes the deployed program ID and a bump. In the website client, market_seed and order_seed are SHA-256 hashes of the respective database IDs encoded as UTF-8. The ABI accepts 32-byte seeds; UUID text is a client convention rather than a program requirement.

Market and order state accounts are owned by the escrow program. Token vaults are owned at the Solana account level by the SPL Token Program; their token authority is the order PDA. The escrow program authorizes releases using that PDA’s seeds through invoke_signed. A native SOL bid holds quote principal on the order account above its protected rent reserve.

market = PDA(["market", launcher_public_key, market_seed], program_id)
order  = PDA(["order", maker_public_key, order_seed], program_id)
vault  = PDA(["vault", order_public_key], program_id)

Persistent account layouts

All integers are little endian. Public keys and seeds are 32 bytes. The market account is 138 bytes, begins with SLMARK01, and stores launcher, fee wallet, base mint, seed, base decimals and bump. The order account is 166 bytes and begins with SLORDER1.

Order side is 0 for ask and 1 for bid. Quote is 0 for SOL and 1 for USDC. Contract status is 0 open, 1 filled, 2 cancelled, or 3 expired. The application can present an open on-chain order as expired by time before a refund instruction changes its terminal state.

Order byte offsetField / type
0Magic SLORDER1 / 8 bytes
8 / 40 / 72Maker pubkey / market pubkey / 32-byte seed
104 / 112 / 120Original quantity / filled quantity / total quote, each u64
128 / 136 / 144Cumulative quote paid / fee paid / market share paid, each u64
152Expiry / i64 Unix seconds
160 / 161 / 162Side / quote / status, each u8
163 / 164 / 165Order bump / vault bump / base decimals, each u8

Instruction set

The first instruction byte is the opcode. The reader rejects truncated or surplus instruction-data bytes. Required token accounts must already exist or be created with ATA instructions earlier in the same transaction. See the full ABI for account metas; unused token-account positions use System Program placeholders.

OpcodeData and effect
0 · InitMarket65 bytes: opcode, market_seed[32], fee_wallet[32]. Launcher signs; records the initialized original SPL mint and immutable fee recipient.
1 · CreateOrder59 bytes: opcode, order_seed[32], side u8, quote u8, quantity u64, quote_total u64, expiry i64. Maker signs; deposits the full ask inventory or bid quote plus fee budget.
2 · Fill25 bytes: opcode, fill_quantity u64, max_buyer_debit u64, expected_filled u64. Taker signs; atomically exchanges assets, routes fees and advances counters.
3 · Cancel / reclaim1 byte. Maker signs; refunds remaining assets or reclaims terminal token-vault surplus and rent.
4 · Expire1 byte. Any caller signs after on-chain expiry; remaining assets are refunded only to the stored maker.

Checks applied to a fill

  • The taker signed, is not the maker, and supplies the expected maker, market, original Token Program and fee recipients.
  • Market, order and vault addresses derive correctly; state ownership, mint and quote identities match the recorded order.
  • The order is open, the on-chain Clock is before expiry, and the expected filled cursor equals the stored counter.
  • Quantity is positive and within the remainder. Quote entitlement is positive, with no positive base remainder left with zero quote entitlement.
  • The nominal buyer quote debit, including fee delta, does not exceed the maximum the taker signed.
  • Transfer accounts have the expected mint and authority. Native SOL principal cannot consume the retained order rent reserve.

A failure rolls back transfers and counter changes together. Fee wallets can equal trading parties or each other; self-transfers do not move funds, while nominal quote and fee accounting still applies.

Cumulative quote and fee accounting

Let N be original base quantity, V the full quote amount and F cumulative filled quantity, all in integer base units. The full quote amount must be at least 100 quote base units. The program uses checked wide intermediates and bounded output amounts.

For a new fill from F0 to F1, it pays the difference between each cumulative entitlement at F1 and F0. It does not independently charge a newly rounded full-order fee for each fragment. This conserves the original funded bid’s quote and fee budget across valid partial fills.

Q(F) = ceil(V × F / N)
Fee(F) = ceil(Q(F) × 50 / 10000)
Market(F) = floor(Fee(F) / 2)
Platform(F) = Fee(F) − Market(F)

Fill quote = Q(F1) − Q(F0)
Fill fee = Fee(F1) − Fee(F0)
Buyer debit = fill quote + fill fee

Refund destinations and retained state

Cancel requires the maker’s signature. Permissionless expiry requires an open order and on-chain time at or after expiry. Both refund only the recorded maker, using the proper base-token or USDC account when needed. Remaining principal, unused fee budget, and unsolicited surplus return to that maker.

Token-vault closure returns its rent. Filled token vaults need a later maker reclaim to close. Market state and terminal order state remain allocated; the terminal order is a tombstone preventing identifier reuse. There is no instruction to change the market fee wallet, reprice a funded order, or let an administrator withdraw a maker’s deposit.

Those are properties of this source, not a guarantee against a future upgrade. Any public deployment must separately disclose its program address, bytecode/source evidence, review status and upgrade-authority policy.