Security Implementation Guide#
Scope: Security policy, vulnerability reporting, and off-chain/operational security for the Seesaw protocol. For the on-chain security model (account access control, arithmetic safety, oracle validation, reentrancy), see architecture/security.md.
1. Account Access Control#
The on-chain program enforces three layers of account validation on every instruction: signer verification, discriminator validation (8-byte type check), and PDA re-derivation. All state-modifying instructions that require authorization verify the signer; lifecycle operations (snapshot, resolve, settle) are permissionless but still require a signer to pay fees.
For the full implementation details — including the discriminator hex table, PDA seed table, and code examples — see architecture/security.md → Account Security.
2. Arithmetic Safety#
All arithmetic uses checked or saturating operations to prevent overflow. Rounding favors the protocol: fees round up (protocol receives more), payouts round down (protocol pays less). The taker fee uses a capped-linear-decay curve: fee_bps(p) = min(fee_cap_bps, decay_rate_bps * (10_000 - p) / 10_000).
For the full implementation details — including the checked-operations table and rounding code examples — see architecture/security.md → Arithmetic Security.
3. Oracle Trust Assumptions#
3.1 Pyth Integration#
The protocol uses Pyth Network as the exclusive oracle provider. It reads the Pyth PriceUpdateV2 account directly at fixed byte offsets — there is no Pyth client SDK dependency — and rejects any account that fails the size, discriminator, or verification-level checks.
Push-feed markets are available for supported Pyth push feeds. Pull-feed markets
depend on the configured Pyth paid API plan and the enabled-feed set for that
plan. The Pyth API key is an infrastructure secret, normally exposed to services
as PYTH_API_KEY; the key value must not be committed, logged, pasted into
release evidence, copied into pull requests, or stored in test fixtures.
3.2 Feed Validation#
The supplied oracle feed is validated against the feed configured for the market, so a market can only ever be resolved against its own asset's price feed. For the full push/pull validation logic and code, see architecture/security.md → Oracle Security.
3.3 Price Validation#
Prices are validated for positivity (price > 0), timeliness (publish_time >= boundary_time), and an optional confidence ratio gate. Once captured, oracle snapshots cannot be modified (idempotency check prevents re-capture).
4. Known Limitations#
4.1 Order Limits#
| Limit | Value | Rationale |
|---|---|---|
| Max bids | 63 | Orderbook account size |
| Max asks | 63 | Orderbook account size |
There is no per-user open-order cap or maximum position size. Earlier versions reserved config fields for such limits, but neither was ever enforced on-chain; do not rely on either existing.
4.2 Position Limits#
- No maximum position size (v1): Users can accumulate unlimited shares
- No leverage: Full collateral required for all orders
- Single settlement: Positions are settled all-at-once
4.3 Market Constraints#
- Configurable durations: 60 seconds to 7 days per market
- Single oracle: Pyth only, no multi-oracle fallback
- No dispute mechanism: Resolution is deterministic from snapshots
5. Upgrade Considerations#
5.1 Account Migration#
If account structures change:
- New accounts use new discriminators
- Migration instruction handles version upgrade
- Reserved fields provide expansion room
5.2 Reserved Fields#
All accounts include reserved space for future fields:
pub _reserved1: [u8; 64],
pub _reserved2: [u8; 64],
pub _reserved3: [u8; 64],
pub _reserved4: [u8; 64],
pub _reserved5: [u8; 36],
5.3 Version Field#
The config account tracks the protocol version:
pub version: u8, // Protocol version for migration support
6. Testing Coverage#
For the full testing environment setup — build commands, test categories, and key research areas — see BUG_BOUNTY.md § 11.
6.1 Unit Tests#
All pure logic functions are covered by unit tests, including outcome computation from oracle snapshots, collateral calculation for orders, order lookup/insertion/removal/compaction, and tick rounding.
6.2 Property Tests#
Property-based tests verify: math operations never overflow, fee rounding favors protocol, tick rounding preserves no-crossed-book invariant, canonical conversion preserves economic equivalence, and resolution is deterministic.
7. Reentrancy Protection#
Solana's runtime provides inherent reentrancy protection: accounts are locked for the transaction, recursive CPI with overlapping writable accounts fails at the runtime level, and SPL Token has no ERC-777-style callback hooks. Settlement is additionally idempotent via a settled flag check.
For the full analysis — including the CEI table and idempotency code — see architecture/security.md → Reentrancy Protection.
8. Contact#
For security issues, please follow responsible disclosure:
- Do NOT exploit or publicize before a fix is available.
- Preferred: Report via the Immunefi bug bounty program.
- Alternative: Email admin@palominito.com (encrypt with our PGP key if sensitive).
- Include detailed reproduction steps.
- Allow reasonable time for a fix (90 days).
The reporting procedures, response timelines, and safe-harbor policy are described in BUG_BOUNTY.md.
9. Off-Chain Security#
9.1 Environment Variables#
Each off-chain service (indexer, web, mobile, and crank) reads its configuration from environment variables, with an .env.example template checked in alongside the service.
Sensitive Variables (Never Commit):
DATABASE_URL- Database connection strings with credentialsCRANK_KEYPAIR- Crank operator private keySENTRY_DSN- Error tracking DSN- Any API keys or secrets
9.2 CORS Configuration#
CORS is configured via the CORS_ALLOWED_ORIGINS environment variable:
# Deny all cross-origin requests (default, most secure)
CORS_ALLOWED_ORIGINS=
# Allow specific origins (production)
CORS_ALLOWED_ORIGINS=https://seesaw.markets,https://staging.seesaw.markets
Important: Empty CORS_ALLOWED_ORIGINS denies all cross-origin requests.
9.3 Security Headers#
The indexer service applies security headers to all responses:
| Header | Value | Purpose |
|---|---|---|
X-Content-Type-Options | nosniff | Prevent MIME sniffing |
X-Frame-Options | DENY | Prevent clickjacking |
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | Force HTTPS |
Content-Security-Policy | default-src 'self'; script-src 'none'; ... | Prevent XSS/injection |
Referrer-Policy | strict-origin-when-cross-origin | Limit referrer leakage |
Permissions-Policy | geolocation=(), microphone=(), camera=() | Disable sensitive APIs |
9.4 Wallet Authentication#
The API uses Solana wallet signatures for authentication:
- Client creates a message with
timestamp,action, andnonce - Client signs the message with their wallet
- Server verifies the signature using
tweetnacl
Replay Attack Prevention:
- Messages expire after 5 minutes
- Nonces are tracked server-side for 10 minutes
- Each nonce can only be used once
9.5 Rate Limiting Tiers#
| Tier | Max Requests | Window | Use Case |
|---|---|---|---|
| Public | 100 | 60s | Unauthenticated endpoints |
| Authenticated | 200 | 60s | Authenticated users |
| Write | 50 | 60s | POST/PUT/DELETE operations |
| Sensitive | 20 | 60s | Follow/unfollow, etc. |
9.6 Security Audit Logging#
The indexer's audit logger tracks security events:
auth_success- Successful authenticationauth_failure- Failed authentication attemptauth_replay_attempt- Nonce reuse (potential attack)rate_limit_exceeded- Rate limit triggeredlarge_trade- Trade above thresholdadmin_action- Administrative operationssuspicious_activity- Anomalous behavior
Logs are structured JSON for SIEM integration.
9.7 HTTPS/TLS Requirements#
Production Requirements:
- HTTPS for HTTP APIs
- WSS for WebSocket connections
- TLS 1.2 or higher
# Production configuration
EXPO_PUBLIC_API_URL=https://api.seesaw.markets
EXPO_PUBLIC_WS_URL=wss://api.seesaw.markets
9.8 Dependency Security#
Run dependency audits regularly:
# JavaScript/TypeScript dependencies
pnpm audit --audit-level moderate
# Rust production dependencies
cargo deny check --exclude-dev
Rust dependency audits cover production dependencies; the dev/test-only dependency paths (Solana test harnesses such as LiteSVM and Mollusk) are tracked separately.
Update Policy:
- Critical/High vulnerabilities: Update within 24 hours
- Medium vulnerabilities: Update within 1 week
- Low vulnerabilities: Update in next release cycle