# Sidelot escrow v1 ABI

No deployed program ID is supplied. All integers are little endian. Pubkeys and seeds are exactly 32 bytes. Original SPL Token only (`Tokenkeg...`), canonical mainnet USDC `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`, platform `DZW2Hho1VMJSGno1inJiKTKosibVmS6NHVfHX76TQruf`.

PDAs: market = `[b"market", launcher pubkey, market_seed]`; order = `[b"order", maker pubkey, order_seed]`; vault = `[b"vault", order pubkey]`.

Enums: side 0 ask/sell, 1 bid/buy; quote 0 native SOL, 1 USDC; status 0 open, 1 filled, 2 cancelled, 3 expired.

Market (138 bytes): magic `SLMARK01` (8), launcher(32), fee_wallet(32), base_mint(32), seed(32), base_decimals(u8), bump(u8).

Order (166 bytes): magic `SLORDER1`(8), maker(32), market(32), seed(32), quantity(u64), filled(u64), quote_total(u64), quote_paid(u64), fee_paid(u64), host_paid(u64), expires_at(i64 UNIX seconds), side(u8), quote(u8), status(u8), bump(u8), vault_bump(u8), base_decimals(u8).

## Instructions

`S` signer, `W` writable. Unused token-account positions must be System Program placeholders. Associated token accounts required by a transfer must already exist, or be created with idempotent ATA instructions in the same transaction before calling the program.

0 InitMarket data: `[0, market_seed(32), fee_wallet(32)]`.
Accounts: launcher(SW), market(W), base_mint(R), system_program(R).

1 CreateOrder data: `[1, order_seed(32), side(u8), quote(u8), quantity(u64), quote_total(u64), expires_at(i64)]`.
Accounts: maker(SW), market(R), order(W), vault(W), maker_source_token(W), base_mint(R), quote_mint(R), token_program(R), system_program(R).
For native SOL quote, quote_mint is System Program. For native SOL bid, maker_source_token is System Program and vault is its derived PDA but is not created; principal is stored in order lamports above rent. Ask source is maker base token account. USDC bid source is maker USDC token account. Creation atomically deposits quantity for asks or quote_total plus full-order buyer fee for bids.

2 Fill data: `[2, quantity(u64), max_buyer_debit(u64), expected_filled(u64)]`.
Accounts: taker(SW), maker(W), market(R), order(W), vault(W), base_mint(R), quote_mint(R), taker_base(W), maker_base(W), taker_quote(W), maker_quote(W), host_wallet(W), platform_wallet(W), host_quote(W), platform_quote(W), token_program(R), system_program(R).
For ask, maker_base is unused. For bid, maker_quote is unused. All *_quote accounts are unused for SOL. taker_base always used; maker_base used for bids. host_wallet and platform_wallet always validated; recipient quote token-account owners must match them. Taker cannot equal maker. Fill requires current filled==expected_filled, open status, Clock time<expiry, positive quantity<=remaining, positive quote delta, no positive remainder with zero quote entitlement, and nominal gross buyer debit<=max_buyer_debit. Maker does not sign.

3 Cancel/reclaim data `[3]`, 4 Expire data `[4]`.
Accounts: caller(SW), maker(W), market(R), order(W), vault(W), maker_refund_token(W), token_program(R).
Cancel requires maker signature. Open orders become cancelled; for filled/cancelled/expired orders it may reclaim unsolicited token-vault donations without changing terminal status. Expire requires open status and Clock time>=expiry; anyone may call, all refunds go only to maker. Refund token is base for asks, USDC for USDC bids, System Program placeholder for native SOL bids. Remaining funds and any unsolicited surplus return to maker; token vault closes and its rent returns to maker. Order remains as a terminal tombstone with rent retained; no order ID reuse.

## Arithmetic and conservation

Price is immutable `quote_total / quantity`, both in asset base units. Full quote_total must be >=100 quote base units. For cumulative filled F, Q(F)=ceil(quote_total*F/quantity), fee(F)=ceil(Q(F)*50/10000), host(F)=floor(fee(F)/2), platform(F)=fee(F)-host(F). Each fill transfers differences of cumulative quantities. Seller receives quote delta, buyer pays quote delta plus fee delta. Odd fee base units go to platform. This makes arbitrary valid partial fills conserve the upfront funded bid; no fees are charged to unused/refunded funds. Checked u128 intermediates, bounded u64 outputs. Fill event is a log plus persisted monotonic counters; account state is authoritative.

SOL order rent is not spendable principal. Token vault rent returns on cancel/reclaim, including reclaim after a completed fill. State rent remains allocated. Frozen accounts fail atomically. Market base mint equal to USDC cannot choose USDC quote. Fee wallets may equal trading parties or each other. Self-transfers are no-ops; nominal gross quote and fees remain recorded, while a buyer receiving its own host fee pays a lower net amount.
