Protocol

Security

PairStreet never holds a user’s keys. Every launch and trade is built on the server as an unsigned transaction and authorized in the user’s wallet. This chapter sets out who controls what, which controls exist, and how each known attack is answered.

Custody assumptions

Custody follows the money. Today, every lamport that moves through a Pair Market moves directly between Solana accounts that its owner controls: the trader’s wallet, the Pump programs’ accounts, the creator’s wallet and the PairStreet PairStreet treasuryPairStreet treasuryThe protocol wallet that receives the protocol share and Pair Vault reserve of creator fees plus the 0.5% trading fee.. PairStreet’s servers hold no key with authority over any of them.

Custody by asset
AssetCustodied byStatus
User SOL and tokensThe user’s wallet. PairStreet builds transactions; the wallet signs them.Live
Bonding-curve reservesThe Pump programLive
Accrued creator feesThe coin’s Pump fee-sharing config, paid out to the creator and the treasuryLive
Protocol revenue and the Pair Vault reserveThe treasury wallet 5XAwPtXHkA2F68tEj5ZAZePJfJWH4tzGkeQiqK5ggfRg, single PairStreet-controlled signerLive
Treasury under multisigA multisig with multiple PairStreet signersPlanned
Settlement asset and Pair Asset per marketThe market’s Pair VaultPair VaultThe account that receives settlement value allocated to one Pair Market, holds it until conversion, and holds the acquired Pair Asset until it is allocated to holders., under one of three custody models: program PDA, multisig, or provider custodyActivates per route

The custody model is a column on every Pair Vault (custody_model: program_pda, multisig, provider_custody). A vault holds assets only once its model is deployed for that market’s instrument. Until then the market’s 25% Pair Vault reservePair Vault reserveThe 25% share of a Pair Market's creator fees earmarked for its Pair Vault. Held by the PairStreet treasury until the market's settlement route activates. accrues in the treasury and is accounted per market.

Program and upgrade authorities

PairStreet deploys no custom onchain program today. It composes existing programs: Pump for creation and trading, the Pump fees program for the creator-fee split, PumpSwap for graduated markets, and the System Program for fee transfers. Upgrade authority for those programs rests with their deployer, not with PairStreet.

Pump program
6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P
Pump fees program
pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ
PumpSwap AMM
pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA

Fee-split authority

At launch, the bonding curve’s creator becomes the coin’s fee-sharing config. The creator then sets the shares once: creator 5,000 bps, treasury 5,000 bps. Pump revokes the config’s admin after that update (adminRevoked = true), and from then on no account can change the shares, PairStreet included. A market whose split did not land shows “Split pending” and only its creator can lock it, from the market page.

Future programs

The Pair Vault program and the Merkle distributor for live claims are part of the settlement architecture. Their upgrade authority is designed to sit with a multisig rather than a single key, and both are audited before activation.

Keys, credentials and secrets

  • ·Mint keypair. For each launch the server generates the new coin’s mint keypair and pre-signs the creation transaction with it. That key’s only role is to sign the creation of that one mint; the launch session holding it is deleted on confirmation.
  • ·Server secrets. The database URL and RPC configuration live in Vercel’s encrypted environment variables. The environment module is server-only and is validated at startup; production refuses to start without a Postgres URL or with a development launch adapter.
  • ·Provider credentials. Routes that need credentials (provider API, RFQ, broker) keep them as server secrets behind the provider interface, never in the client bundle. Executing a live acquisition also requires a configured vault signer; providers refuse to purchase without one.
  • ·Uploads and metadata. Images are checked by their magic bytes, not their declared type: PNG, JPG, GIF and WEBP up to 4 MB. SVG is rejected. Token metadata JSON is immutable once written and is served at a permanent URI.
  • ·Headers. Every response sets X-Content-Type-Options: nosniff, X-Frame-Options: DENY, a strict-origin referrer policy, and a permissions policy that disables camera, microphone and geolocation.

Pause controls and rate limits

Pause controls

Two status fields act as switches. Both are enforced on the server.

Pause controls
ControlValuesEffect
Instrument statusactive · paused · coming_soon · provider_unavailable · deprecatedAny value other than active rejects new launches into the instrument, makes the Eligibility Engine return INSTRUMENT_UNAVAILABLE, and adds a blocker to every Pair Router plan for it.
Pair Market statuspending · active · paused · settlement_disabled · closedThe settlement scheduler selects only active markets. The token keeps trading on Pump in every state; settlement runs only while the market is active.

Rate limits

Write endpoints use a per-IP token bucket, per endpoint, refilled continuously. Requests above the budget receive HTTP 429. Request bodies above 64 KB are rejected before parsing, and every body is validated against a schema.

Rate limits per IP
EndpointPer minute
POST /api/trade/quote120
POST /api/trade/execute30
POST /api/launch/confirm12
POST /api/rewards/claim12
POST /api/markets/[mint]/fees12
POST /api/pair-requests10
POST /api/upload10
POST /api/launch/prepare6

Buckets are held in memory on each server instance. A shared store for rate limits and replay protection, so limits hold across instances, is Planned.

Transaction simulation and confirmation

  • ·The client simulates every prepared transaction against the network before asking the wallet for a signature. A failed simulation stops the flow; nothing is signed.
  • ·Trades carry a minimum output derived from the user’s slippage setting, so a trade that would fill worse than the quote fails onchain instead of filling.
  • ·Every transaction carries a recent blockhash and a last valid block height. A transaction that has not landed by then expires; a retry builds a fresh one.
  • ·Launch confirmation verifies the signature on chain: the transaction exists, did not fail, contains the expected mint and creator, and the bonding curve exists. Only then is the Pair Market registered.
  • ·Claims require a signed wallet intent: a message naming the action, the wallet, a SHA-256 digest of the exact payload and the issue time, verified as an ed25519 signature. Intents expire after five minutes and are single use. On the development network, launch and trade requests are authorized the same way; on mainnet, the wallet’s signature on the transaction itself is the authorization.

Reconciliation and monitoring

recomputeFromLedger rebuilds a market’s Pair aggregates from ledger rows alone; tests assert the stored read model equals it for every market. Blocked settlements are recorded with status failed and their blockers in the error column. Each indexer source writes its last run time, status and last error to indexer_cursors. Server errors are logged with their route. See Accounting.

Alerting on indexer errors and on drift between the ledger and onchain vault balances is part of the vault custody rollout, alongside the public proof page.

Audit status

Threat model

Each threat below lists the risk, the mitigation and the assumption that remains. Mitigations marked live are implemented and tested today; mitigations marked architecture are the design that ships with Pair Vault custody and settlement.

Threat model
ThreatRiskMitigationRemaining assumption
Reward snapshot manipulationA wallet buys moments before a snapshot and captures rewards it did not hold for.Live Time-weighted balance is the default: weight is Σ balance × seconds held inside the epoch, so a last-second buy earns a last-second share. snapshot_min_hold pays only holders who held continuously for a minimum share of the epoch. Both are tested.Weights are as accurate as the indexed balance history; live holder indexing is in integration.
Wash tradingArtificial volume makes a market look active.Live Holder weight uses balance over time, never volume, so wash volume earns nothing. Every round trip pays Pump’s fees and the 0.5% PairStreet fee.Reported 24h volume from DexScreener includes wash volume; analytics show it as reported.
Self tradingThe creator trades their own coin to collect holder rewards.Live The creator wallet is excluded from rewards by default, along with liquidity accounts, the vault and any configured wallets.A creator using fresh wallets is a Sybil case.
Sybil walletsHoldings are split across many wallets to gain more weight.Live Allocation is proportional to balance-time, which is additive: ten wallets holding a tenth each weigh exactly what one wallet holding everything weighs. An optional minimum holding drops dust wallets.Region rules apply per request, not per person.
Vault authority compromiseA key that controls a Pair Vault is stolen.Architecture Vaults use program PDA or multisig custody, with no single server key. The executor and the vault authority are separate. Audit before activation.Until treasury multisig, the reserve sits with a single-signer treasury.
Provider quote manipulationA distorted quote leads to a poor acquisition.Live Quotes come from Jupiter’s aggregated routes with price impact recorded; the full plan is persisted on the settlement row; execution price is written to the purchase row. Architecture Execution enforces a slippage bound against the quote.Some SPL instruments have thin onchain liquidity.
Stale pricingPair Value or a plan uses an outdated price.Live Every reference price is stored with its timestamp. Quotes are cached for at most 30 seconds. Settlements on Jupiter routes refresh the reference price from the execution price.Listed instruments without an onchain asset use their price source’s own update cadence.
ReplayA signed request or transaction is submitted twice.Live Solana transactions expire with their blockhash and signatures are unique. Wallet intents expire after five minutes and are single use. Launch sessions are keyed per mint and deleted on confirmation.The intent replay set is held per instance; a shared store is planned.
Double claimsOne allocation is paid out twice.Live Allocations move from claimable to claimed in one database transaction, conditional on their state; any mismatch aborts the claim. Allocations are unique per epoch and wallet. Tested.Live claims activate with the Merkle distributor, designed to record each claimed leaf onchain.
Rounding extractionFractional remainders are skimmed across many small allocations.Live All amounts are integer base units. Each share is floored and the leftover units go to the largest remainders, so allocations sum to the pool exactly and no surplus exists.USD values are display figures; base units are authoritative.
Indexer divergenceThe offchain ledger drifts from chain.Live Sources are idempotent and checkpointed. Launches are verified on chain; fee splits are read back from chain; allocations are committed to a Merkle root; the read model is rebuildable from the ledger.Reconciling vault token accounts against the ledger activates with custody.
Front-running settlementA trader buys the Pair Asset ahead of a known settlement.Architecture Settlements are batched per market per epoch, sized to the vault balance, and executed with a slippage bound. Cadence is configurable per market.Settlement timing is public by design; batching limits what it reveals.
Provider insolvencyThe issuer of a Pair Asset fails.Live Each instrument records its issuer, verification level, transfer restrictions and issuer documents. Moving its status off active stops new launches and settlements into it.Issuer credit risk stays with the issuer’s instrument.

Failure handling for each of these cases is covered in Failure Modes. The reward methods referenced here are specified in Holder Rewards.