{"path":"docs/adr/0001-dual-pda-architecture.md","size":1634,"locked":false,"binary":false,"truncated":false,"content":"# ADR 0001: Dual PDA Architecture (GigEscrow + Vault)\n\n## Status\nAccepted\n\n## Context\nEach job needs an account to store metadata (client, freelancer, oracle, status) and a separate mechanism to hold escrowed SOL. A single combined account was considered first.\n\n## Decision\nUse two separate PDAs per job: `GigEscrow` (Anchor-owned, stores state) and `Vault` (System Program-owned, holds lamports only).\n\n## Rationale\nNative SOL transfers via CPI require the sending account to be owned by the System Program. Anchor's `#[account]` macro assigns program ownership to the account for data validation — this conflicts with the System Program's signer-authority requirements needed for a lamport transfer CPI. Merging state and vault into one account would require either:\n1. Routing transfers through `**lamports().borrow_mut()`* manual manipulation (bypasses System Program safety checks, higher audit risk), or\n2. A custom CPI wrapper (added complexity, no compute savings).\n\nTwo PDAs, each derived deterministically from `(client_pubkey, job_id)`, is the standard, auditable pattern for this problem on Solana.\n\n## Consequences\n- Two account creations per job instead of one → slightly higher rent cost (recovered on close via `close = client`).\n- Both PDA bumps must be stored on `GigEscrow` at init to avoid recomputing `find_program_address` on every resolution call (~50,000 CU savings per settlement transaction — see ADR 0003).\n- Any future audit needs to verify both PDAs independently, which is more auditing surface than a single-account design, but each account has a narrower, easier-to-reason-about responsibility.\n"}